【问题标题】:Fragment in ViewPager is not displaying anything in its RecyclerView on rotationViewPager 中的片段在其 RecyclerView 旋转时未显示任何内容
【发布时间】:2016-03-19 07:01:06
【问题描述】:

我在与 TabLayout 集成的 ViewPager 中有 4 个片段。这些 Fragments 中的每一个都包含一个 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();
    }
}

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();
        }
    }

我在这里查看了很多帖子,多次更改了我的代码,但我仍然无法让它工作。当我单击其中一个日期按钮时,我只是对它“修复”感到困惑。如果您希望我发布更多代码,请告诉我。很抱歉这篇长文,但我觉得需要上下文。非常感谢任何帮助!

【问题讨论】:

  • 你在哪里声明和初始化isAdded()
  • @HRaval 是 Fragment 的内置函数,用于检查它是否附加到活动。
  • 试试this,希望对你有帮助
  • @Nisarg 我在发布之前尝试过,它不起作用:/

标签: android android-fragments android-viewpager fragmentpageradapter


【解决方案1】:

我想通了!我不得不切换到FragmentStatePagerAdapter 而不是使用FragmentPagerAdapter。我认为这与 Fragments 被销毁并重新创建有关。

我还读到另一种方法是将 ViewPager 包装在 Fragment 中,并在创建它的适配器时使用 getChildFragmentManager() 而不是 getSupportFragmentManager(),如下所示:

mAdapterViewPager = new MyPagerAdapter(getChildFragmentManager());

我不想为了解决这个问题而在 ViewPager 周围添加整个 Fragment,所以我改用 FragmentStatePagerAdapter 并且它成功了!希望这对其他人有帮助。

【讨论】:

  • FragmentPagerAdapter 未被弃用。
【解决方案2】:

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

【讨论】:

  • 欢迎来到 SO。这应该是评论,而不是回答。
  • @AllLelopath 看起来他无法发表评论,因为他没有足够的代表
  • 啊,是的,我的错。向@VictorIrechukwu 道歉
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多