【问题标题】:RecyclerView in FragmentPagerAdaper only updates when screen is rotatedFragmentPagerAdapter 中的 RecyclerView 仅在屏幕旋转时更新
【发布时间】:2015-06-17 11:37:17
【问题描述】:

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

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

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

这是来自父活动的代码:

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,就会显示内容。

我不知道新信息是否会改变任何东西。我仍然很困,肯定需要帮助。

【问题讨论】:

  • 你能显示onCreate方法的代码吗..
  • @Moinkhan 我刚刚添加了一些代码。
  • 您在哪里交换光标并通知 RecyclerView 更改?
  • super.onCreate(savedInstanceState);移动到onCreate的第一行试试这个..
  • @Selvin ,我在 onLoadFinished() 回调方法中交换光标作为 LoaderManager.Callback 方法的一部分。

标签: android android-fragments android-recyclerview fragmentpageradapter


【解决方案1】:

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

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

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

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

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

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

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

【讨论】:

    【解决方案2】:

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

    为什么有效..?

    在您的代码中,您已将super.onCreate() 放在方法的末尾。并且您首先应用了您的代码。因此,您正在迫使 android 停止其默认实现 onCreate(),这很糟糕。 因为在他们的方法中,他们正在执行所有初始化和 UI 相关任务

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

    希望你能理解。

    【讨论】:

    • 伙计,实际上它并没有解决我的问题。很抱歉我不能接受你的回答。但感谢您的建议。已注明。
    • 还没有。今晚我会继续努力。这是一个个人项目。
    • 伴侣我仍然卡住了,但我意识到如果我等待 LoaderManager 完成加载(1-2 秒),然后再滑动到包含 Loader 的 Fragment,就会显示内容。我不知道新信息是否会改变任何东西。
    • 好的,我也意识到执行时间可能是问题......所以你可以让用户等待内容显示的进度..
    • 我发布了我的解决方案以防您有兴趣。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-15
    • 1970-01-01
    • 2013-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多