我将 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 NavigationBottomNavigation 结合使用非常酷 - 更多详情 here

无论哪种方式,以这种方式存储的所有值都将在 activity 关闭后丢失,static 值将在应用程序关闭后丢失。如果您想在应用程序运行之间保留此值 - 使用 SharedPreference 或其他一些存储,如文件缓存或数据库。

使用static 变量不是很好,但也不坏。这个的主要缺点 - 你可以习惯它,最终由于缺乏适当的数据流,应用程序将变得更难维护。

希望对您有所帮助