如何避免每次通过切换片段来创建Fragment对象?
我只有一个活动的应用程序与4个片段切换底部选项卡菜单。所以它一次只能在屏幕上显示4个片段之一。看起来很简单,但我问自己为什么通过切换片段,每次都必须重新创建新的Fragment对象?这是从Android文档:如何避免每次通过切换片段来创建Fragment对象?
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
// Replace the contents of the container with the new fragment
ft.replace(R.id.your_placeholder, new FooFragment());
// or ft.add(R.id.your_placeholder, new FooFragment());
// Complete the changes added above
ft.commit();
我可以尝试存储由我自己片段的引用,每次挑现成的对象,但我发现这样的片段使用风格的建筑,所以它可能是错的?
您可以在ViewPager中设置片段,并切换ViewPager页面。
试试这个:
viewPager = (ViewPager) findViewById(R.id.viewpager);
FragmentAdapter adapter = new FragmentAdapter(getSupportFragmentManager());
adapter.addFragment(new ExplorerFragment(), "Fragment1", false);
adapter.addFragment(new NotificationFragment(), "Fragment2", false);
adapter.addFragment(new HistoryFragment(), "Fragment3", false);
adapter.addFragment(new AccountFragment(), "Fragment4", false);
viewPager.setAdapter(adapter);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
switch (id){
case R.id.action_explorer:
viewPager.setCurrentItem(0);
final Menu bottomMenu = bottomNavigationView.getMenu();
final MenuItem targetMenuItem = bottomMenu.getItem(0);
targetMenuItem.setChecked(true);
break;
case R.id.action_notification:
viewPager.setCurrentItem(1);
final Menu bottomMenu1 = bottomNavigationView.getMenu();
final MenuItem targetMenuItem1 = bottomMenu1.getItem(1);
targetMenuItem1.setChecked(true);
break;
case R.id.action_history:
viewPager.setCurrentItem(2);
final Menu bottomMenu2 = bottomNavigationView.getMenu();
final MenuItem targetMenuItem2 = bottomMenu2.getItem(2);
targetMenuItem2.setChecked(true);
break;
case R.id.action_account:
viewPager.setCurrentItem(3);
final Menu bottomMenu4 = bottomNavigationView.getMenu();
final MenuItem targetMenuItem4 = bottomMenu4.getItem(3);
targetMenuItem4.setChecked(true);
break;
case R.id.action_search:
break;
}
return true;
}
});
EDIT1:如何创建NonSwipeableViewPager:
public class NonSwipeableViewPager extends ViewPager {
public NonSwipeableViewPager(Context context) {
super(context);
setMyScroller();
}
public NonSwipeableViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
setMyScroller();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
// Never allow swiping to switch between pages
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// Never allow swiping to switch between pages
return false;
}
//down one is added for smooth scrolling
private void setMyScroller() {
try {
Class<?> viewpager = ViewPager.class;
Field scroller = viewpager.getDeclaredField("mScroller");
scroller.setAccessible(true);
scroller.set(this, new MyScroller(getContext()));
} catch (Exception e) {
e.printStackTrace();
}
}
public class MyScroller extends Scroller {
public MyScroller(Context context) {
super(context, new DecelerateInterpolator());
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, 350 /*1 secs*/);
}
}
}
,然后在你的XML:
<com.project.Components.NonSwipeableViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/bottom_navigation"/>
我知道ViewPager只有通过实现滑动浏览的网页。你知道是否有可能禁用任何类型的动画和轻扫手势,只是使其立即替换碎片? –
另外我见过ViewPager一次只保留有限数量的片段。所以如果它只有3的缓存,那么我的情况下,位于边缘的碎片将不断重新创建。 –
是的。您只需创建一个自定义的ViewPager组件。我将使用代码@ArnieSchwarzvogel编辑我的文章 –
创建的所有片段一次,并用它或者使你的片段对象成为一个单例来实现它。
辛格尔顿例子:
class MyFragment extends Fragment{
private static MyFragment instance;
public static MyFragment getInstance(){
if(instance == null)
instance = new MyFragment();
return instance;
}
}
使用MyFragment.getInstance();
现在,它不会产生新的对象,每次创建对象片段。
您可以将TAG
添加到您的片段,同时更换,然后再使用FragmentManager
的findFragmentByTag
检索:
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
// Replace the contents of the container with the new fragment
Fragment fooFrag = fm.findFragmentByTag("foo-frag-tag");
if(fooFrag == null) {
fooFrag = new FooFrag();
}
ft.replace(R.id.your_placeholder, fooFrag, "foo-frag-tag");
// or ft.add(R.id.your_placeholder, new FooFragment());
// Complete the changes added above
ft.commit();
好主意。 –
不幸的是,这不起作用--FragmentManager不会简单地缓存片段,它仅与putFragment()结合使用,这是一个完全不同的故事 –
看到我更新的答案 –