2

我在ViewPager中有4个片段与TabLayout集成。这些碎片中的每一个都有一个RecyclerView,因为我显示的是未知数量的列表项。这些项目是按日期加载的,所以我有两个按钮可让您更改日期,然后根据设置的日期加载列表项目中的相应数据。按钮是外部活动的一部分。ViewPager中的片段在其RecyclerView中不显示任何东西

到目前为止的一切都很完美,但是一旦我旋转设备,碎片不会加载任何东西。碎片内没有显示任何内容。虽然外部活动的视图显示得很好。奇怪的是,如果我触摸其中一个更改日期的按钮,则会加载碎片并正确显示数据。但是我需要在旋转后立即显示所有内容,而不仅仅是当我点击其中一个按钮时。这里是我的代码:

public class MainActivity extends AppCompatActivity implements DatePickerFragment.DateDialogInterface 
{ 
    private final static String COLOR_CONTROL_CHOSEN = "color_control_chosen"; 
    private static final String DIALOG_DATE = "dialog_date"; 
    private static final String TAG = "MainActivity"; 
    private static final String SET_LOCATION = "set_location"; 
    public static final String LEAGUE_POSITION = "league_position"; 
    private Toolbar mToolbar; 
    private ViewPager mViewPager; 
    private TabLayout mTabLayout; 
    private ImageButton mPrevDateButton, mNextDateButton; 
    private TextView mDateTextView, mLeagueTextView; 
    private String mTodaysDate; 
    private Date mLastSelectedDate, mTodaysDateObj; 
    private ProgressBar mProgressBar; 
    private FragmentPagerAdapter mAdapterViewPager; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     mToolbar = (Toolbar) findViewById(R.id.outnix_toolbar); 
     mViewPager = (ViewPager) findViewById(R.id.main_activity_view_pager); 
     mTabLayout = (TabLayout) findViewById(R.id.main_activity_tab_layout); 
     mDateTextView = (TextView) findViewById(R.id.display_date_text_view); 
     mLeagueTextView = (TextView) findViewById(R.id.league_title_header); 
     mPrevDateButton = (ImageButton) findViewById(R.id.previous_date_button); 
     mNextDateButton = (ImageButton) findViewById(R.id.next_date_button); 
     mProgressBar = (ProgressBar) findViewById(R.id.loading_circle); 
     mProgressBar.setVisibility(View.GONE); 
     setTodaysDate(); 
     mDateTextView.setText("Today"); 

     setSupportActionBar(mToolbar); 
     assert getSupportActionBar() != null; 
     getSupportActionBar().setDisplayShowTitleEnabled(false); 

     NavDrawerFragment navDrawerFrag = (NavDrawerFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_nav_drawer); 
     navDrawerFrag.setUp((DrawerLayout) findViewById(R.id.nav_drawer), mToolbar); 

     setUpViewPagerAdapterOnCreate(); 
     mTabLayout.setupWithViewPager(mViewPager); 

     mDateTextView.setOnClickListener(new View.OnClickListener() 
     { 
      @Override 
      public void onClick(View v) 
      { 
       FragmentManager fm = getSupportFragmentManager(); 
       DatePickerFragment dialog = new DatePickerFragment(); 
       Bundle args = new Bundle(); 
       args.putSerializable("ARG_DATE", mLastSelectedDate); 
       dialog.setArguments(args); 
       dialog.show(fm, DIALOG_DATE); 
      } 
     }); 

    THESE TWO LISTENERS ARE WHAT DISPLAY THE DATA AFTER A ROTATION CHANGE 
    ////////////////////////////////////////////////////////////////// 
     mPrevDateButton.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) 
      { 
       mProgressBar.setVisibility(View.VISIBLE); 
       updateDate(-1); 
       setupViewPagerAdapter(getViewPagerPos()); 
      } 
     }); 

     mNextDateButton.setOnClickListener(new View.OnClickListener() 
     { 
      @Override 
      public void onClick(View v) 
      { 
       mProgressBar.setVisibility(View.VISIBLE); 
       updateDate(1); 
       setupViewPagerAdapter(getViewPagerPos()); 
      } 
     }); 
    } 
    //////////////////////////////////////////////////////////////////// 
/* @Override 
    protected void onResume() 
    { 
     super.onResume(); 
     setupViewPagerAdapter(getViewPagerPos()); 
    }*/ 

    private void setUpViewPagerAdapterOnCreate() //only called when opened from LauncherActivity 
    { 
     setupViewPagerAdapter(0); 

     int touchColorPixel = getIntent().getIntExtra(COLOR_CONTROL_CHOSEN, ContextCompat.getColor(this, R.color.blue)); 

     if(touchColorPixel == ContextCompat.getColor(this, R.color.orange)) 
      mViewPager.setCurrentItem(0); 
     else if(touchColorPixel == ContextCompat.getColor(this, R.color.blue)) 
      mViewPager.setCurrentItem(1); 
     else 
      mViewPager.setCurrentItem(3); 
    } 

    private void setupViewPagerAdapter(int currentPos) 
    { 
     mAdapterViewPager = new MainPagerAdapter(getSupportFragmentManager()); 

     mViewPager.setAdapter(mAdapterViewPager); 
     mViewPager.setOffscreenPageLimit(4); 
     mViewPager.setCurrentItem(currentPos); 
    } 

    @Override 
    protected void onSaveInstanceState(Bundle outState) 
    { 
     super.onSaveInstanceState(outState); 
     outState.putSerializable(DIALOG_DATE, mLastSelectedDate);   //save the last date selected (or last date displayed) on rotation change. 
    } 

    @Override 
    protected void onRestoreInstanceState(Bundle savedInstanceState) 
    { 
     super.onRestoreInstanceState(savedInstanceState); 
     setDateFromDialog((Date) savedInstanceState.getSerializable(DIALOG_DATE)); //restore the last date selected to the new rotation change 
    } 

    public ProgressBar getProgressBar() 
    { 
     return mProgressBar; 
    } 

    @Override 
    public void setDateFromDialog(Date date) 
    { 
     String newDate = getFormattedDate(date); 
     updateTodaysDate();  
     mLastSelectedDate = date; 

     setupViewPagerAdapter(getViewPagerPos()); 

     if(newDate.equals(mTodaysDate)) 
      mDateTextView.setText("Today"); 
     else 
      mDateTextView.setText(newDate); 
    } 

    private int getViewPagerPos() 
    { 
     return mViewPager.getCurrentItem(); 
    } 
} 

的2个按钮mPrevDateButtonmNextDateButton是当点击“修复”的问题的按钮。在他们的点击监听器中,updateDate()方法只做与TextView对象相关的东西,这就是为什么我没有包含定义(我试图尽可能缩短发布时间)。所以我肯定知道它与我的setupViewPagerAdapter()方法有关。我已经尝试在onCreate()onResume()中添加此方法,但片段仍然保持空白。

这里是我的ViewPager适配器代码:

public class MainPagerAdapter extends FragmentPagerAdapter 
{ 
    private final String[] mFragmentTitleList = {"My Games", "All Games", "All Places", "My Places"}; //tab title names 
    private final static int NUM_FRAGMENTS = 4; 

    public MainPagerAdapter(FragmentManager fm) 
    { 
     super(fm); 
    } 

    @Override 
    public Fragment getItem(int position) 
    { 
     switch(position) 
     { 
      case 0: 
       return MyGamesFragment.newInstance(); 
      case 1: 
       return AllGamesFragment.newInstance(); 
      case 2: 
       return AllPlacesFragment.newInstance(); 
      case 3: 
       return MyPlacesFragment.newInstance(); 
      default: 
       return null; 
     } 
    } 

    @Override 
    public int getCount() 
    { 
     return NUM_FRAGMENTS; 
    } 

    @Override 
    public CharSequence getPageTitle(int position) 
    { 
     return mFragmentTitleList[position]; 
    } 
} 

这里是4个片段之一。他们几乎都有类似的设计。

public class AllGamesFragment extends Fragment 
{ 
    private SwipeRefreshLayout mSwipeRefreshLayout; 
    private RecyclerView mAllGamesRecyclerView; 
    private GameAdapter mGameAdapter; 
    private List<Game> mGameList = new ArrayList<>(); 
    private MainActivity mMainActivity;  //keeps a reference to MainActivity to access public methods 

    public static AllGamesFragment newInstance() 
    { 
     return new AllGamesFragment(); 
    } 

    @Override 
    public void onAttach(Context context) 
    { 
     super.onAttach(context); 
     mMainActivity = (MainActivity) context; 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setRetainInstance(true); 
     mMainActivity.getProgressBar().setVisibility(View.VISIBLE); 
    } 

    @Nullable 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    { 
     View view = inflater.inflate(R.layout.recycler_view_all_games, container, false); 
     mAllGamesRecyclerView = (RecyclerView) view.findViewById(R.id.all_games_recycler_view); 
     mAllGamesRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); 
     mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_refresh); 
     mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() 
     { 
      @Override 
      public void onRefresh() 
      { 
       getGamesData(); 
       mSwipeRefreshLayout.setRefreshing(false); 
      } 
     }); 

     return view; 
    } 

    @Override 
    public void onResume() 
    { 
     super.onResume(); 
     getGamesData(); 
    } 

    private void setupAdapter() 
    { 
     if(isAdded()) 
     { 
      mGameAdapter = new GameAdapter(mGameList); 
      mAllGamesRecyclerView.setAdapter(mGameAdapter); 
     } 
    } 

    private void getGamesData() 
    { 
     new GetDataTask(mMainActivity.getLastSelectedDate()).execute(); 
    } 

    private class GetDataTask extends Scraper.GameDataTask 
    { 
     GetDataTask(Date date) 
     { 
      super(date, getActivity()); 
     } 

     @Override 
     protected void onPostExecute(List<Game> games) 
     { 
      mGameList = games; 
      setupAdapter(); 
      mMainActivity.getProgressBar().setVisibility(View.GONE); 
     } 
    } 

    private class GameAdapter extends RecyclerView.Adapter<GameHolder> 
    { 
     private List<Game> mGames; 

     public GameAdapter(List<Game> games) 
     { 
      mGames = games; 
     } 

     @Override 
     public GameHolder onCreateViewHolder(ViewGroup parent, int viewType) 
     { 
      LayoutInflater inflater = LayoutInflater.from(getActivity()); 
      View view = inflater.inflate(R.layout.list_game_item, parent, false); 
      return new GameHolder(view, getActivity()); 
     } 

     @Override 
     public void onBindViewHolder(GameHolder holder, int position) 
     { 
      holder.bindGameData(mGames.get(position)); 
     } 

     @Override 
     public int getItemCount() 
     { 
      return mGames.size(); 
     } 
    } 

我已经看过这么多的帖子在这里,多次改变了我的代码,我仍然无法得到它的工作。当我点击其中一个日期按钮时,我感到困惑,它“修复了”。如果你想让我发布更多的代码让我知道。对不起,对于长篇文章,但我觉得上下文是必要的。我非常感谢任何帮助!

+0

你声明并初始化的地方是isAdded() –

+0

@HRaval是一个片段的内置函数,用于检查它是否附加到一个活动。 –

+0

尝试[这](http://stackoverflow.com/a/17629575/3117966),希望它会有所帮助 – Nisarg

回答

3

我明白了!我不得不切换到FragmentStatePagerAdapter而不是使用FragmentPagerAdapter。我相信这与碎片被破坏和再次重现有关。

我也读到另一种方法是将包裹ViewPager的片段,当你创建它的适配器使用getChildFragmentManager()而非getSupportFragmentManager()这样的:

mAdapterViewPager = new MyPagerAdapter(getChildFragmentManager()); 

我不想有加我的ViewPager周围的整个碎片只是为了解决这个问题,所以我切换到使用FragmentStatePagerAdapter,它的工作!希望这可以帮助别人。

0

使viewPager适配器扩展FragmentStatePagerAdapter而不是FragmentPagerAdapter应该解决问题。

+0

欢迎来到SO。这应该是一个评论,而不是一个答案。 –