Drawer NavigationView + Fragments with viewpager,如何避免在导航抽屉中的片段从一个切换到另一个时缓存数据?
Drawer NavigationView + Fragments with viewpager, how to avoid caching data when switching fragments in navigation drawer from one to another?
我在左侧有一个抽屉导航视图,它连接到具有不同 viewpager 的不同片段。结构如下
主要活动
抽屉 NavigationView
| Fragment A -- ViewPagerA ----Tab1 - Fragment1
Tab2 - Fragment2
| Tab3 - Fragment3
| Fragment B -- ViewPagerB ----Tab1 - Fragment4
Tab2 - Fragment5
| Tab3 - Fragment6
Fragment1-6 是列表视图片段。
问题是当我从Fragment A切换到Fragment B时,viewpager会从Fragment1缓存列表视图的内容,并尝试将缓存的内容显示给Fragment4的适配器。以至于我第一次从导航抽屉中切换片段时总是显示错误信息。
我的代码:
主要活动:
public class MainActivity extends Activity {
@InjectView(R.id.navigation_view) public NavigationView mNavigationView;
@InjectView(R.id.drawerLayout) public DrawerLayout mDrawerLayout;
//......Layout injections..............///
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDrawerToggle = new ActionBarDrawerToggle(this,mDrawerLayout, mToolbar,R.string.app_name,
R.string.app_name){
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
};
}
public void setUpToggle()
{
mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
// This method will trigger on item Click of navigation menu
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
if (menuItem.isChecked()) menuItem.setChecked(false);
else menuItem.setChecked(true);
//Closing drawer on item click
mDrawerLayout.closeDrawers();
switch (menuItem.getItemId()) {
case R.id.a_drawer:
startFragment(FragmentA.newInstance());
return true;
case R.id.b_drawer:
startFragment(FragmentB.newInstance());
return true;
default:
Toast.makeText(getApplicationContext(),"More things need to be added",Toast.LENGTH_SHORT).show();
return true;
}
}
});
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerToggle.syncState();
}
}
片段A/B(完全相同的结构和布局)
public class TabFragment extends Fragment {
public static TabLayout tabLayout;
public static ViewPager viewPager;
public static int int_items = n; //n is any positive integer
private Context mContext;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/**
*Inflate tab_layout and setup Views.
*/
View tabView = inflater.inflate(R.layout.fragment_tab,null);
tabLayout = (TabLayout) tabView.findViewById(R.id.tabs);
viewPager = (ViewPager) tabView.findViewById(R.id.viewpager);
viewPager.setAdapter(new MyAdapter(getChildFragmentManager()));
tabLayout.post(new Runnable() {
@Override
public void run() {
tabLayout.setupWithViewPager(viewPager);
}
});
return tabView;
}
class MyAdapter extends FragmentStatePagerAdapter{
public MyAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position)
{
switch (position){
case 0 : return new Fragment1();//or Fragment4 5 6 here
case 1 : return new Fragment2();
case 2 : return new Fragment3();
default:return new Fragment1();
}
}
@Override
public int getCount() {
return int_items;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position){
case 0 :
return "F1";
case 1 :
return "F2";
case 2 :
return "F3";
}
return null;
}
}
片段 1 - 6:
public class TabFocusFragmentextends extends Fragment
implements LoaderManager.LoaderCallbacks<Cursor>
{
private TabFocusAdapter mAdapter;
private List<E> mList;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadData();// never been executed,:(
setHasOptionsMenu(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_tab_focus, container, false);
loadData();
setupRecyclerView();
return view;
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onLoadMore() {
if(NeedLoad)
loadData();
}
private void loadData() {
//RequestData
……
}
private void setupRecyclerView() {
…...
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(mActivity, ContentProvider.createUri(E.class, null),
null, null, null, null);
}
@Override //fragment starts here, why??
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if (loadedList.size() > 0) {
//crashes here …...
if (!fullPacketLoaded) {
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
如果新片段列表适配器不适合显示以前的内容,它将崩溃。
基于这个问题,您是否也对下面的问题有更好的解决方案?
终于修复了。
在我实现 LoaderManager 片段的 onCreate() 方法中,我这样做了
getLoaderManager().initLoader(0, null, this);
if(!getLoaderManager().getLoader(0).isReset()) {
getLoaderManager().restartLoader(0, null, this);
}
当新加载程序未正确激活时它可以工作。
我在左侧有一个抽屉导航视图,它连接到具有不同 viewpager 的不同片段。结构如下
主要活动 抽屉 NavigationView
| Fragment A -- ViewPagerA ----Tab1 - Fragment1
Tab2 - Fragment2
| Tab3 - Fragment3
| Fragment B -- ViewPagerB ----Tab1 - Fragment4
Tab2 - Fragment5
| Tab3 - Fragment6
Fragment1-6 是列表视图片段。
问题是当我从Fragment A切换到Fragment B时,viewpager会从Fragment1缓存列表视图的内容,并尝试将缓存的内容显示给Fragment4的适配器。以至于我第一次从导航抽屉中切换片段时总是显示错误信息。
我的代码:
主要活动:
public class MainActivity extends Activity {
@InjectView(R.id.navigation_view) public NavigationView mNavigationView;
@InjectView(R.id.drawerLayout) public DrawerLayout mDrawerLayout;
//......Layout injections..............///
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDrawerToggle = new ActionBarDrawerToggle(this,mDrawerLayout, mToolbar,R.string.app_name,
R.string.app_name){
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
};
}
public void setUpToggle()
{
mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
// This method will trigger on item Click of navigation menu
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
if (menuItem.isChecked()) menuItem.setChecked(false);
else menuItem.setChecked(true);
//Closing drawer on item click
mDrawerLayout.closeDrawers();
switch (menuItem.getItemId()) {
case R.id.a_drawer:
startFragment(FragmentA.newInstance());
return true;
case R.id.b_drawer:
startFragment(FragmentB.newInstance());
return true;
default:
Toast.makeText(getApplicationContext(),"More things need to be added",Toast.LENGTH_SHORT).show();
return true;
}
}
});
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerToggle.syncState();
}
}
片段A/B(完全相同的结构和布局)
public class TabFragment extends Fragment {
public static TabLayout tabLayout;
public static ViewPager viewPager;
public static int int_items = n; //n is any positive integer
private Context mContext;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/**
*Inflate tab_layout and setup Views.
*/
View tabView = inflater.inflate(R.layout.fragment_tab,null);
tabLayout = (TabLayout) tabView.findViewById(R.id.tabs);
viewPager = (ViewPager) tabView.findViewById(R.id.viewpager);
viewPager.setAdapter(new MyAdapter(getChildFragmentManager()));
tabLayout.post(new Runnable() {
@Override
public void run() {
tabLayout.setupWithViewPager(viewPager);
}
});
return tabView;
}
class MyAdapter extends FragmentStatePagerAdapter{
public MyAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position)
{
switch (position){
case 0 : return new Fragment1();//or Fragment4 5 6 here
case 1 : return new Fragment2();
case 2 : return new Fragment3();
default:return new Fragment1();
}
}
@Override
public int getCount() {
return int_items;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position){
case 0 :
return "F1";
case 1 :
return "F2";
case 2 :
return "F3";
}
return null;
}
}
片段 1 - 6:
public class TabFocusFragmentextends extends Fragment
implements LoaderManager.LoaderCallbacks<Cursor>
{
private TabFocusAdapter mAdapter;
private List<E> mList;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadData();// never been executed,:(
setHasOptionsMenu(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_tab_focus, container, false);
loadData();
setupRecyclerView();
return view;
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onLoadMore() {
if(NeedLoad)
loadData();
}
private void loadData() {
//RequestData
……
}
private void setupRecyclerView() {
…...
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(mActivity, ContentProvider.createUri(E.class, null),
null, null, null, null);
}
@Override //fragment starts here, why??
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if (loadedList.size() > 0) {
//crashes here …...
if (!fullPacketLoaded) {
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
如果新片段列表适配器不适合显示以前的内容,它将崩溃。
基于这个问题,您是否也对下面的问题有更好的解决方案?
终于修复了。
在我实现 LoaderManager 片段的 onCreate() 方法中,我这样做了
getLoaderManager().initLoader(0, null, this);
if(!getLoaderManager().getLoader(0).isReset()) {
getLoaderManager().restartLoader(0, null, this);
}
当新加载程序未正确激活时它可以工作。