FragmentPagerAdapter 中的 RecyclerView 仅在屏幕旋转时更新

RecyclerView in FragmentPagerAdaper only updates when screen is rotated

我在 FragmentPagerAdpater 中有一个片段。 Fragment 基本上是一个 RecyclerView。 RecyclerView 的源由 Fragment 内的 Loader 提供。

我的问题是列表在首次实例化时显示为空。但是当我旋转屏幕时,它看起来很好。

你知道什么地方会出错吗? 如果需要,我很乐意提供一些(或很多)代码。告诉我你想看哪些部分。

这是来自父 activity 的代码:

public class MyFragmentPagerAdapter extends FragmentPagerAdapter {

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

    @Override
    public Fragment getItem(int i) {
        switch (i) {
            case 0:
                //We return an instance of the RouteListFragment
                RouteListFragment frag = RouteListFragment.getInstance(session.getId());
                return frag;
            case 1:
                //We return an instance of the RouteSpotListFragment
                RouteSpotListFragment frag2 = RouteSpotListFragment.getInstance(sessionSpot.getId());
                return frag2;
            default :
                return null;
        }

    }

Fragment中的主要方法:

public static RouteListFragment getInstance (int sessionId){
    RouteListFragment frag = new RouteListFragment();
    Bundle bundle = new Bundle ();
    bundle.putInt(SESSION_ID, sessionId);
    frag.setArguments(bundle);
    return frag;
}

/* (non-Javadoc)
 * @see android.app.Fragment#onCreate(android.os.Bundle)
 */
@Override
public void onCreate(Bundle savedInstanceState) {
    //We extract the RouteList from the Bundle
    Bundle bundle = getArguments();
    sessionId = bundle.getInt(SESSION_ID);

    //We create a MyRouteListAdapter with a null cursor
    Cursor cursor = null;
    routeListAdapter = new MyRouteListAdapter(cursor, getActivity());
    updateList();

    super.onCreate(savedInstanceState);
}

/* (non-Javadoc)
 * @see android.app.Fragment#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)
 */
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    //Inflate the layout
    layout = (RelativeLayout) inflater.inflate(R.layout.fragment_route_list, container, false);

    routeSource = new RouteDataSource (getActivity());

    //Now that we have the routeSource, we can prepare the routeListAdapter
    routeRecyclerList = (RecyclerView) layout.findViewById(R.id.route_list_view);
     // use a linear layout manager
    mLayoutManager = new LinearLayoutManager(getActivity());
    routeRecyclerList.setLayoutManager(mLayoutManager);

    routeRecyclerList.setAdapter(routeListAdapter);

    return layout;
}

    public void updateList(){
    /*
     * we get the loaderManager to start the query
     * If a Loader has already been initiated, we need to reload it. Otherwise the 
     * onCreateLoader callback method will not be called
     * Else, we initiate a Loader
     */
    LoaderManager manager = getLoaderManager();
    if (manager.getLoader(LOADER_GET_ALL_ROUTES)!= null)    
        manager.restartLoader(LOADER_GET_ALL_ROUTES, null, this);
    else manager.initLoader(LOADER_GET_ALL_ROUTES, null, this);

}

最后,我在 onLoadFinished() 回调方法中交换光标作为 LoaderManager.Callback 方法的一部分。

编辑:我刚刚意识到,如果我等待 LoaderManager 完成加载(1-2 秒),在滑动包含 Loader 的 Fragment 之前,内容是显示。

我不知道新信息是否有任何改变。我仍然很困惑,绝对需要帮助。

super.onCreate(savedInstanceState)移动到第一行...

Why it works ..?

在您的代码中,您已将 super.onCreate() 置于方法的末尾。并且您首先应用了您的代码。所以你强迫 android 停止他们默认的 onCreate() 实现,这是不好的。 因为在他们的方法中他们正在做所有的初始化和UI相关任务

所以最好总是在第一行调用 super()

希望你明白。

我终于解决了我的问题,方法如下:

1 - 将 FragmentPagerAdapter 更改为 FragmentStatePagerAdapter。原因是 FragmentPagerAdapter 不会在需要时重新创建您的片段。它把一切都保存在记忆中。所以如果你的Fragment在创建的时候没有完全运行,或者你想稍后刷新它,那你就麻烦了。

2 - 从片段中删除 LoaderManager 结构,让父级 Activity 处理查询数据库。这样,我可以让 FragmentStatePagerAdapter 首先实例化一个空片段,然后 activity 可以告诉适配器在查询返回后重新创建片段。为了重新创作,我需要 FragmentStatePagerAdapter

3 - 覆盖我的 FragmentStatePagerAdapter 的 getItemPosition() 以便在我调用 PagerAdapter 上的 notifyDataSetChanged() 时重新创建所有片段:

public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

因为我的片段不太复杂,加载的数据也不大,所以我不介意重新创建我所有的片段。因此使用 POSITION_NONE 在性能方面是可以的。

我希望这个小发现可以帮助其他人。 =)