Эффективно ли управлять созданием фрагментов Android? - PullRequest
1 голос
/ 29 апреля 2019

У меня есть ViewPager, внутри которого у меня есть 4 вкладки с fragments. Ранее при запуске приложения оно просто загружало два первых fragments по умолчанию. Имеет смысл, но проблема заключалась в том, что каждый раз, когда я переходил на 4-ю вкладку и возвращался к первой вкладке, ее приходилось создавать заново. Чтобы создать мой fragments только один раз, я использовал этот метод:

mViewPager.setOffscreenPageLimit(3);

Итак, предыдущая проблема исчезла, и я могу перемещаться по всем fragments, не создавая их снова. Но новая проблема заключается в том, что при запуске приложения все fragments создаются сразу. И так как у меня есть сетевые вызовы в каждом fragment, происходят множественные сетевые вызовы, и это может вызвать проблемы (это также не логично в соответствии с моим дизайном приложения). Теперь мне нужно найти способ решить проблему. Помощь приветствуется.

Изменить:

Одним из решений является использование viewPager.addOnPageChangeListener() и размещение там сетевых вызовов, как предлагал @Ferran. Звучит хорошо! Но я сталкиваюсь с другой проблемой. Когда fragment выбран в onPageSelected(int position), все его поля представления являются нулевыми, несмотря на то, что я определил их все в методе onCreateView() (Поскольку все fragments создаются при запуске приложения, эти поля представления не должны быть null), и я не могу обработать результат сетевого вызова и установить данные в представлениях. Я получаю fragments по этому коду:

Fragment fragment = adapter.getItem(position);

Обратите внимание, что сам объект fragment не равен нулю.

Вот типичные фрагменты, которые я использовал:

открытый класс TabFragmentPayment расширяет Fragment реализует View.OnClickListener {

private LinearLayout llError, llLoading, llNoItem;
private LinearLayout llPaymentRecords, llImageUpload;
private Button btnTryAgain; //here it just works for transaction get.
private RecyclerView rcv;
private ImageView ivPic, ivNationalCardPreview, ivSelect, ivAddAccount;
private TextView tvUploadPic, tvRequestPayment, tvNationalCardMessage;
private Spinner spBankAccounts;
private View view;
private ArrayList<Transaction> paymentRecordList = new ArrayList<>();
private ArrayList<Bank> bankList = new ArrayList<>();
private long minToPay = -1;
public static boolean checkAccounts = false;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    view = inflater.inflate(R.layout.fragment_payment, null);
    setWidgetReferences();
    setClickListeners();
    setupActivity();
    return view;
}


private void setWidgetReferences() {
    ivPic = view.findViewById(R.id.ivfpPic);
    ivSelect = view.findViewById(R.id.ivfpSelect);
    ivAddAccount = view.findViewById(R.id.ivfpAddAccount);
    tvUploadPic = view.findViewById(R.id.tvfpUpload);
    tvRequestPayment = view.findViewById(R.id.tvfpRequestPayment);
    spBankAccounts = view.findViewById(R.id.spfpSelectAccount);
    llError = view.findViewById(R.id.llError);
    llLoading = view.findViewById(R.id.llLoading);
    llNoItem = view.findViewById(R.id.llNoItem);
    btnTryAgain = view.findViewById(R.id.btnReload);
    rcv = view.findViewById(R.id.rcvfpTransactions);
    ivNationalCardPreview = view.findViewById(R.id.ivfpNationalCardPreview);
    tvNationalCardMessage = view.findViewById(R.id.tvfpNationalCardMessage);
    llPaymentRecords = view.findViewById(R.id.llfpPayment);
    llImageUpload = view.findViewById(R.id.llfpImageUpload);
}

private void setClickListeners() {
    ivSelect.setOnClickListener(this);
    ivPic.setOnClickListener(this);
    ivAddAccount.setOnClickListener(this);
    tvUploadPic.setOnClickListener(this);
    tvRequestPayment.setOnClickListener(this);
    btnTryAgain.setOnClickListener(this);
}
}

А вот как я пытаюсь получить фрагмент в родительском Activity:

@Override
 public void onPageSelected(int position) {
      Fragment fragment = adapter.getItem(position);
      if (fragment instanceof TabFragmentPayment) {
           TabFragmentPayment fr = (TabFragmentPayment) fragment;      
      }             
}

И результирующий фрагмент с именем fr имеет нулевые поля просмотра, что странно для меня.

1 Ответ

0 голосов
/ 29 апреля 2019

елей всего. setOffscreenPageLimit(4) приказать адаптеру создать еще 4 страницы при создании первой. Таким образом, вы можете перемещаться по 5 страницам без перезагрузки. В вашем случае, я думаю, нет необходимости использовать это.

Чтобы убедиться, что ваши сетевые вызовы не вызываются при каждом создании, вы можете сделать это следующим образом

Поместите свой сетевой вызов в отдельный метод для каждого фрагмента и сделайте его общедоступным.

Тогда используйте это

    viewPager.setAdapter(adapter);
    viewPager.setOffscreenPageLimit(4); 
    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int i, float v, int i1) {
        }

        @Override
        public void onPageSelected(int i) {
            // here you can call tour public fragment method
            // i = page index
            Fragment page = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.viewpager + ":" + viewPager.getCurrentItem());
            // replace R.id.viewpager with your viewpager id
            // then call your public method
            ((YourFragmentClass)page).your_public_method();
        }

        @Override
        public void onPageScrollStateChanged(int i) {

        }
    });

В первый раз, onPageSelected не запускается, потому что страница не была выбрана, а только создана, но onPageScrolled делает. Итак, поиграйте с этими двумя методами, чтобы вызывать методы фрагментов.

...