如何在视图翻页器中更改选项卡时更新列表

8
在我的应用程序中,我使用ViewPager实现了导航选项卡。我已经成功地使用以下代码绘制了选项卡:

https://github.com/codepath/android_guides/wiki/Sliding-Tabs-with-PagerSlidingTabStrip

我使用滑动选项卡和ViewPager来获取导航选项卡。一切都正常工作,但是当我移动到其他选项卡时,列表不会得到更新。在调试时,OnResume()被调用,并且对象列表变量也得到了更新,但是列表在视觉上没有得到更新。
以下是一些代码片段:

对于我的情况下的Tab1:即活动选项卡

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

        if(!internetUtil.isConnectedToInternet(getActivity())){
            mSwipeRefreshLayout.setEnabled(false);
        }else{
            mSwipeRefreshLayout.setEnabled(true);
            new GetUsersFromServerTask().execute();  // Here i am making the network calls 
        }
}

在Tab2上:这是存档选项卡。
 @Override
    public void onResume() {
        super.onResume();
        new GetUsersArchivedFromServerTask().execute(); // Network calls
    }

在MainActivity中:
public class MaterialTab extends FragmentActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.material_main_sample);
        ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
        viewPager.setAdapter(new SampleFragmentPagerAdapter(getSupportFragmentManager()));
        PagerSlidingTabStrip tabsStrip = (PagerSlidingTabStrip) findViewById(R.id.tabs);
        tabsStrip.setViewPager(viewPager);
        tabsStrip.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                if(position == 0){
                   ActiveFragment activeFragment = new ActiveFragment();
                    final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                    ft.detach(activeFragment);
                    ft.attach(activeFragment);
                    ft.commit();
                } if(position == 1){
                    ArchiveFragment archiveFragment = new ArchiveFragment();
                    final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                    ft.detach(archiveFragment);
                    ft.attach(archiveFragment);
                    ft.commit();
                }
            }
        });
    }
}

同时,当我进行下拉刷新时,列表会得到更新。我现在完全困惑了为什么会出现这种行为。当我滑动选项卡时,调用的是同样的方法,但列表没有被更新,但当我进行下拉刷新时,它会被更新。

这是活动片段:

public class ActiveFragment extends Fragment {

public void updateFragment(){
        new GetUsersArchivedFromServerTask().execute();
    }

 public class GetUsersArchivedFromServerTask extends AsyncTask<User, Void, String> {
        @Override
        protected String doInBackground(Shipment... parmas) {
            // Log.d(TAG, String.valueOf(shipmentDbHandler.getAllActiveShipments().size()));
            _userList1 = userDbHandler.getAllActiveUserByToday(DateTimeUtil.getCurrentTime());
            return "";
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected void onPostExecute(String str) {
            // Set the refresh Listener to false after the list has been loaded with new set of data
            if (mSwipeRefreshLayout.isRefreshing()) {
                mSwipeRefreshLayout.setRefreshing(false);
            }

            if(_userList1.size() == 0){
                ViewGroup parentOne = (ViewGroup) viewOne.getParent();
                if(parentOne != null){
                    parentOne.removeView(viewOne);
                }
            }

            if(_shipmentList1.size() > 0 ){
                mShipmentAdapter = new ShipmentAdapter(getActivity(),_userList1,1); 
                shipmentListView1.setAdapter(mShipmentAdapter);
                setListViewHeightBasedOnChildren(shipmentListView1);
                ViewGroup parentOne = (ViewGroup) viewOne.getParent();
                if(parentOne == null){
                    mainLayoutOne.addView(viewOne);
                }

                mShipmentAdapter.notifyDataSetChanged();
            }
            mSwipeRefreshLayout.setClickable(true);
        }
    }
}   
7个回答

4
请使用FragmentStatePagerAdapter来实现该功能。

1
View Pager 也会加载旁边的 Fragment,因此 onResume 方法已经被调用,所以当你滑动到该 Fragment 时,onResume 不会再次被调用。 - Anand Makwana

3

你的OnPageChangeListener正在影响片段。每次选择一个页面,你都会创建一个新的Fragment并将其添加进去。你试图分离一个尚未连接的新Fragment,这是完全混乱的。你的SampleFragmentPagerAdapter将为你处理这些片段事务。因此,只需删除你的setOnPageChangeListener即可,一切都会好起来。


3
这里有一个简单且有效的解决方案。只需像这样替换setOnPageChangeListener,我们使用getSupportFragmentManager访问当前片段的实例,并调用相应的片段方法。
    tabsStrip.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {
            Fragment currentFragment = getSupportFragmentManager()
                    .findFragmentByTag(
                            "android:switcher:" + R.id.viewpager + ":"
                                    + mViewPager.getCurrentItem());
            if (currentFragment instanceof ActiveFragment) {
                ((ActiveFragment) currentFragment).updateFragment();
            } else if (currentFragment instanceof ArchiveFragment) {
                ((ArchiveFragment) currentFragment).updateFragment();
            }
        }
    });

在你的相应片段中,放置updateFragment()方法。
public void updateFragment() {
    Toast.makeText(getActivity(), "ActiveFragment", Toast.LENGTH_SHORT)
            .show();
    // make updates over here
    // new GetUsersArchivedFromServerTask().execute(); // Network calls
}

参考链接


我尝试了这种方法,但对于其余的元素却出现了空指针异常。 - anand
“rest of the elements” 是什么意思? - Chitrang
布局中的其余元素指的是我有下拉刷新(swipeRefresh)和按钮,然后所有这些都会导致空指针异常。 - anand
我请求您将该片段类放入您的问题中,以便我们可以更清楚地了解。 - Chitrang
我已经张贴了代码片段... 我无法放置整个代码,我已经发布了ActiveFragment的片段。 - anand
在不查看代码的情况下,很难找出导致NPE的原因,你可能会错过传递异步类的某些内容。我还不清楚viewOne.getParent()是什么意思?如果您提供片段类的完整源代码将是很好的。 - Chitrang

2
  1. 从页面更改监听器中删除 onPageSelected(...) 代码,不需要手动附加/分离,ViewPager 会自动处理。并且你的 SampleFragmentPagerAdapter 应该在 getItem(...) 中创建每个 Fragment 实例。

  2. new GetUsersFromServerTask().execute() 应该在每个 Fragment 的 onCreateView 中调用,然后在 Asynctask 完成后更新视图。


此外,您应该注意 OffscreenPageLimit

public void setOffscreenPageLimit(int limit)

设置在闲置状态下视图层次结构中当前页面两侧应保留的页面数。超出此限制的页面将在需要时从适配器中重新创建。

这是作为一种优化提供的。如果您事先知道需要支持的页面数量或者已经在页面上实现了惰性加载机制,则调整此设置可以提高分页动画和交互的感知流畅度。如果您只有少量页面(3-4),可以同时保持活动状态,那么在用户前后翻页时,新创建的视图子树的布局所花费的时间将更少。

您应该将此限制保持较低,特别是如果您的页面具有复杂的布局。此设置默认为 1。


我已经移除了片段的附加和分离,但现在片段内部没有任何方法被调用。我认为它正在缓存这些片段。 - anand
实际上,ViewPager 总是将相邻的 Fragment 缓存起来,这意味着相邻的 Fragment 会与当前 Fragment 一起被调用。因此,当您移动到相邻的 Fragment 时,您可能看不到它正在更新,实际上它已经更新了。 - Xcihnegn

1
在你的片段中使用这个。
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);

    if (isVisibleToUser) {
        // Do your code here
    }
}

每当选项卡对用户可见时,都会调用此方法。希望这可以解决你的问题!!!

谢谢您的帮助。这是唯一帮助我完成应用程序的东西! - user3079872

0
尝试使用notifyDataChange或notifyall。

0

重写setPrimaryItem()方法,并在该位置调用您的片段的refresh()方法。setPrimaryItem()viewPager中每次选择的项目更改时都会被调用。它可能会被调用多次,因此您也必须处理它。 请参见:setPrimaryItem

希望这可以帮助到您。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接