我将 ViewPager 的当前项存储在应用程序的子类字段中以供将来参考。有更好的解决方案吗?
I'm storing a ViewPager's current item in an Application's subclass field for future reference. Is there a better solution?
我有一个使用 BottomNavigationView
的主 activity,其中第一个 Fragment
有一个带有一些选项卡的嵌套 ViewPager
。当我导航到第二个或第三个 "main fragment" 然后返回到第一个(持有选项卡的那个)时,我想恢复我离开时处于活动状态的选项卡。
为了实现这一点,我将 viewPager 的当前项目保存在片段的 onPause
...
@Override
public void onPause() {
super.onPause();
App.homeTab = viewPager.getCurrentItem();
Log.v(DEBUG_TAG, "item: " + App.homeTab);
}
作为 App.homeTab
静态提交到我的 Application
的子类中:
public class MyApp extends Application {
public static int homeTab = 0;
// [...]
... 然后我在片段的 onCreateView
中检索该值,如下所示:
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_home, container, false);
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(
getContext(),
getChildFragmentManager(),
HomeCategoryContent.Elements
);
viewPager = root.findViewById(R.id.view_pager);
viewPager.setAdapter(sectionsPagerAdapter);
Log.d(DEBUG_TAG,"restored tab: " + App.homeTab);
viewPager.setCurrentItem(App.homeTab);
// [...]
SectionsPagerAdapter
直接从 Android Studio 的模板扩展 FragmentPagerAdapter
。
它可以工作,但不知何故,每次我不得不使用对某些 UI 组件的静态引用时,我都会感到有点不舒服...
有更好的解决方案吗?
这个容易内存泄露吗?
在这种情况下,static
变量不是必需的。您可以将值存储在仍然是 "alive" 的任何地方,例如 - activity 实例变量。看起来像这样
((MyActivity)getActivity()).setFirstPagerPosition(position)
((MyActivity)getActivity()).getFirstPagerPosition()
更好的方法是将 activity 作为某个接口的实例传递给片段,它将像这样实现
interface FirstPagerPositionStorage {
void setFirstPagerPosition(position);
int getFirstPagerPosition();
}
class MyActivity extends Activity implements FirstPagerPositionStorage{
...
}
MyFragment.newInstance((FirstPagerPositionStorage)this)
class MyFragment extends Fragment {
FirstPagerPositionStorage listener;
static MyFragment newInstance(FirstPagerPositionStorage listener){
MyFragment fragment = new MyFragment();
fragment.listener = listener;
return fragment;
}
}
不要使用 onPause
方法来存储这样的值使用 OnPageSelectedListener
of ViewPager
有一个方法 onPageSelected(int position)
- 用它来存储值
viewPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageScrollStateChanged(int arg0) { }
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) { }
@Override
public void onPageSelected(int position) {
listener.setFirstPagerPosition(position);
//or if you will go with activity methods
((MyActivity)getActivity()).setFirstPagerPosition(position);
}
});
如果你选择监听方式,不要忘记检查当前activity是否在片段onAttach
方法
中实现了这个接口
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (!(context instanceof FirstPagerPositionStorage)){
throw IllegalStateException("Activity must implement FirstPagerPositionStorage");
}
}
这是更简单、更经典的 Android 方式。现代方式是在所有底部导航片段之间使用共享 ViewModel
大多数现代应用程序将以这种方式实现。与 Jetpack Navigation
和 BottomNavigation
结合使用非常酷 - 更多详情 here
无论哪种方式,以这种方式存储的所有值都将在 activity 关闭后丢失,static
值将在应用程序关闭后丢失。如果您想在应用程序运行之间保留此值 - 使用 SharedPreference
或其他一些存储,如文件缓存或数据库。
使用static
变量不是很好,但也不坏。这个的主要缺点 - 你可以习惯它,最终由于缺乏适当的数据流,应用程序将变得更难维护。
希望对您有所帮助
我有一个使用 BottomNavigationView
的主 activity,其中第一个 Fragment
有一个带有一些选项卡的嵌套 ViewPager
。当我导航到第二个或第三个 "main fragment" 然后返回到第一个(持有选项卡的那个)时,我想恢复我离开时处于活动状态的选项卡。
为了实现这一点,我将 viewPager 的当前项目保存在片段的 onPause
...
@Override
public void onPause() {
super.onPause();
App.homeTab = viewPager.getCurrentItem();
Log.v(DEBUG_TAG, "item: " + App.homeTab);
}
作为 App.homeTab
静态提交到我的 Application
的子类中:
public class MyApp extends Application {
public static int homeTab = 0;
// [...]
... 然后我在片段的 onCreateView
中检索该值,如下所示:
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_home, container, false);
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(
getContext(),
getChildFragmentManager(),
HomeCategoryContent.Elements
);
viewPager = root.findViewById(R.id.view_pager);
viewPager.setAdapter(sectionsPagerAdapter);
Log.d(DEBUG_TAG,"restored tab: " + App.homeTab);
viewPager.setCurrentItem(App.homeTab);
// [...]
SectionsPagerAdapter
直接从 Android Studio 的模板扩展 FragmentPagerAdapter
。
它可以工作,但不知何故,每次我不得不使用对某些 UI 组件的静态引用时,我都会感到有点不舒服...
有更好的解决方案吗? 这个容易内存泄露吗?
static
变量不是必需的。您可以将值存储在仍然是 "alive" 的任何地方,例如 - activity 实例变量。看起来像这样
((MyActivity)getActivity()).setFirstPagerPosition(position)
((MyActivity)getActivity()).getFirstPagerPosition()
更好的方法是将 activity 作为某个接口的实例传递给片段,它将像这样实现
interface FirstPagerPositionStorage {
void setFirstPagerPosition(position);
int getFirstPagerPosition();
}
class MyActivity extends Activity implements FirstPagerPositionStorage{
...
}
MyFragment.newInstance((FirstPagerPositionStorage)this)
class MyFragment extends Fragment {
FirstPagerPositionStorage listener;
static MyFragment newInstance(FirstPagerPositionStorage listener){
MyFragment fragment = new MyFragment();
fragment.listener = listener;
return fragment;
}
}
不要使用 onPause
方法来存储这样的值使用 OnPageSelectedListener
of ViewPager
有一个方法 onPageSelected(int position)
- 用它来存储值
viewPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageScrollStateChanged(int arg0) { }
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) { }
@Override
public void onPageSelected(int position) {
listener.setFirstPagerPosition(position);
//or if you will go with activity methods
((MyActivity)getActivity()).setFirstPagerPosition(position);
}
});
如果你选择监听方式,不要忘记检查当前activity是否在片段onAttach
方法
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (!(context instanceof FirstPagerPositionStorage)){
throw IllegalStateException("Activity must implement FirstPagerPositionStorage");
}
}
这是更简单、更经典的 Android 方式。现代方式是在所有底部导航片段之间使用共享 ViewModel
大多数现代应用程序将以这种方式实现。与 Jetpack Navigation
和 BottomNavigation
结合使用非常酷 - 更多详情 here
无论哪种方式,以这种方式存储的所有值都将在 activity 关闭后丢失,static
值将在应用程序关闭后丢失。如果您想在应用程序运行之间保留此值 - 使用 SharedPreference
或其他一些存储,如文件缓存或数据库。
使用static
变量不是很好,但也不坏。这个的主要缺点 - 你可以习惯它,最终由于缺乏适当的数据流,应用程序将变得更难维护。
希望对您有所帮助