我有一个ViewPager
,其中有四个带有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
对象本身不是null。
这是我使用过的典型片段:
公共类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的视图字段为空,这对我来说很奇怪。
答案 0 :(得分:0)
全部解决。
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
,这是第一次。因此,请使用这两种方法来调用片段方法。