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。這應該是一個評論,而不是一個答案。 –