Я храню текущий элемент ViewPager в поле подкласса приложения для дальнейшего использования. Есть ли лучшее решение? - PullRequest
0 голосов
/ 24 апреля 2020

У меня есть основное действие, использующее BottomNavigationView, где первый Fragment имеет вложенную ViewPager с некоторыми вкладками. Когда я перехожу ко второму или третьему «основному фрагменту», а затем go возвращаюсь к первому (тот, который содержит вкладки), я хотел бы восстановить вкладку, которая была активной, когда я уходил.

Для достижения это я сохраняю текущий элемент viewPager в onPause ...

@Override
public void onPause() {
    super.onPause();
    App.homeTab = viewPager.getCurrentItem();
    Log.v(DEBUG_TAG, "item: " + App.homeTab);
}

, являющемся App.homeTab stati c, поданным в мой подкласс 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 расширяет FragmentPagerAdapter прямо из шаблона Android Studio .

Это работает, но почему-то я чувствую себя немного некомфортно каждый раз, когда мне приходится использовать ссылку c stati на какой-то компонент пользовательского интерфейса ...

Существуют ли лучшие решения? Этот склонен к утечке памяти?

1 Ответ

1 голос
/ 08 мая 2020

static переменные не обязательны в этом случае. Вы можете хранить значение везде, например, что еще «живое» - переменная экземпляра действия. Это будет выглядеть следующим образом:

((MyActivity)getActivity()).setFirstPagerPosition(position)

((MyActivity)getActivity()).getFirstPagerPosition()

. Лучший подход - передать активность фрагменту как экземпляр некоторого интерфейса, который он реализует следующим образом.

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 из 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);
            }

        });

Если вы выбрали способ прослушивания, не забудьте проверить, реализует ли текущая деятельность этот интерфейс фрагментарно onAttach метод

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    if (!(context instanceof FirstPagerPositionStorage)){
        throw IllegalStateException("Activity must implement FirstPagerPositionStorage");
    }

}

Это было проще и более классическим c Android способом. Современный способ заключается в использовании общего доступа ко всем нижним фрагментам навигации ViewModel

Большинство современных приложений будут реализованы таким образом. Это довольно круто использовать в сочетании с Jetpack Navigation и BottomNavigation - подробнее здесь

В любом случае все значения, сохраненные таким образом, будут потеряны и после закрытия действия. значение static будет потеряно после закрытия приложения. Если вы хотите сохранить это значение между запусками приложения - используйте SharedPreference или другое хранилище, такое как файловый кеш или база данных.

Использование static переменных не очень хорошо, но совсем не плохо. Основной недостаток этого - вы можете привыкнуть к нему, и в конечном итоге приложение станет намного сложнее поддерживать из-за отсутствия надлежащего потока данных.

Надеюсь, это поможет

...