当片段在 FragmentPagerAdapter 中完全初始化时等待事件以使用数据设置它们
Wait for event when fragments fully initialized in FragmentPagerAdapter to setup them with data
我有一个 activity 正在折叠 AppBarLayout
。在 onCreate()
方法中,我向服务器发送请求以获取一些数据。并根据我得到的数据 - 我需要在运行时动态选择要显示给用户的视图:1. MyFragment1;或 2. TabLayout
/ViewPager
和 FragmentPagerAdapter
,其中有两个片段。我需要为这些片段设置一些数据。但是接下来的问题是:我已经有数据并在我的适配器中将其设置为片段,但是片段方法 onCreate
尚未被调用,并且我的布局未初始化。这就是我在将数据填充到布局视图时崩溃的原因。那么,我怎样才能以某种方式制作 - 首先创建片段并初始化它的字段,然后才用数据设置它?谢谢。
private MenuFragment1 menu1Fragment1;
private MenuFragment3 menu1Fragment3;
private TabMenuAdapter adapter;
private void setupViewPager(ViewPager viewPager) {
menu1Fragment1 = new MenuFragment1();
menu1Fragment3 = new MenuFragment3();
adapter = new TabMenuAdapter(getSupportFragmentManager());
adapter.addFragment(menu1Fragment1, "Menu 1");
adapter.addFragment(menu1Fragment3, "Menu 2");
viewPager.setAdapter(adapter);
}
public onDataLoaded(String data)
{
//at this point, fragment is created, but it's View fields are NULL!!
menu1Fragment1.data = data;
}
@Layout(id = R.layout.content_shop_final)
public class ShopFinalTermsFragment extends BaseFragment {
private static final String SANS_SERIF_FAMILY_NAME = "sans-serif";
private static final String SANS_SERIF_MEDIUM_FAMILY_NAME = "sans-serif-medium";
private InfoModel InfoModel;
private RateModel RateModel;
@BindView(R.id.shop_final_nested_scroll_view)
NestedScrollView nestedScrollView;
@BindView(R.id.shop_final_pending_txt)
TextView pendingDurationTxt;
@BindView(R.id.shop_final_rate_cond_rv)
RecyclerView rateCondRv;
@BindView(R.id.shop_final_description_txt)
TextView descriptionTxt;
@Inject
ToolsManager toolsManager;
RateConditionsAdapter adapter;
private String getParams;
public static ShopFinalTermsFragment newInstance(String getParams, InfoModel shopInfoModel, RateModel RateModel) {
ShopFinalTermsFragment fragment = new ShopFinalTermsFragment();
Bundle args = new Bundle();
args.putString(SHOP_GET_PARAMS, shopGetParams);
args.putSerializable(INFO_MODEL_KEY, shopInfoModel);
args.putSerializable(MODEL_KEY, userCashbackRateModel);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
this.GetParams = getArguments().getString(SHOP_GET_PARAMS);
this.InfoModel = (InfoModel) getArguments().getSerializable(INFO_MODEL_KEY);
this.RateModel = (RateModel) getArguments().getSerializable(RATE_MODEL_KEY);
}
}
@Override
protected void setupInOnCreateView() {
nestedScrollView.setVisibility(View.VISIBLE);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
conditionsTxt.setTypeface(Typeface.create(SANS_SERIF_FAMILY_NAME, Typeface.BOLD));
} else {
conditionsTxt.setTypeface(Typeface.create(SANS_SERIF_MEDIUM_FAMILY_NAME, Typeface.NORMAL));
}
}
@Override
protected void inject() {
ShopsComponent shopsComponent = DaggerShopsComponent.builder()
.applicationComponent(((BaseActivity) getActivity()).getApplicationComponent())
.build();
shopsComponent.inject(this);
}
public void setupWithData(InfoModel InfoModel, RateModel RateModel) {
//THIS METHOD IS COLLED FROM ACTIVITY'S onDataLoaded(InfoModel InfoModel, RateModel RateModel) method
setupShopInformation(shopInfoModel);
setCashBackRateModel(userCashbackRateModel);
}
}
您以错误的方式使用了依赖项。应该在片段上调用 setupWithData
的不是 activity,而应该是从 activity(或其他存储)获取数据的片段。这样,您将打破对最终未初始化的片段生命周期的依赖。
从服务器获取数据,将其存储在您需要的地方,然后从您的 activity 更新 UI。此时你要么显示 MyFragment1
,要么显示你的 TabLayout/ViewPager
。如果它是 TabLayout
或 ViewPager
,您所做的就是创建片段并将其添加到布局或相应的寻呼机适配器中。而已。您此时不设置数据。
现在,当您的内部片段填充到寻呼机适配器中时,它们将经历 onAttach
、onCreate
、onStart
和 onResume
生命周期方法。 onResume
是加载数据的好地方。您可以直接从片段访问它,也可以从出站 activity 获取它 - 取决于什么对您更有意义。如果您需要 activity 引用,您可以通过片段中的 getActivity()
方法访问它。
因此在该片段的 onResume
中,您将拥有类似的内容:
setupShopInformation((YourActivity) getActivity()).getShopInfoModel());
setCashBackRateModel((YourActivity) getActivity()).getUserCashbackRateModel());
尽管以某种状态存储它会更好 class。但这将是一个单独的问题。
祝你好运!
我有一个 activity 正在折叠 AppBarLayout
。在 onCreate()
方法中,我向服务器发送请求以获取一些数据。并根据我得到的数据 - 我需要在运行时动态选择要显示给用户的视图:1. MyFragment1;或 2. TabLayout
/ViewPager
和 FragmentPagerAdapter
,其中有两个片段。我需要为这些片段设置一些数据。但是接下来的问题是:我已经有数据并在我的适配器中将其设置为片段,但是片段方法 onCreate
尚未被调用,并且我的布局未初始化。这就是我在将数据填充到布局视图时崩溃的原因。那么,我怎样才能以某种方式制作 - 首先创建片段并初始化它的字段,然后才用数据设置它?谢谢。
private MenuFragment1 menu1Fragment1;
private MenuFragment3 menu1Fragment3;
private TabMenuAdapter adapter;
private void setupViewPager(ViewPager viewPager) {
menu1Fragment1 = new MenuFragment1();
menu1Fragment3 = new MenuFragment3();
adapter = new TabMenuAdapter(getSupportFragmentManager());
adapter.addFragment(menu1Fragment1, "Menu 1");
adapter.addFragment(menu1Fragment3, "Menu 2");
viewPager.setAdapter(adapter);
}
public onDataLoaded(String data)
{
//at this point, fragment is created, but it's View fields are NULL!!
menu1Fragment1.data = data;
}
@Layout(id = R.layout.content_shop_final)
public class ShopFinalTermsFragment extends BaseFragment {
private static final String SANS_SERIF_FAMILY_NAME = "sans-serif";
private static final String SANS_SERIF_MEDIUM_FAMILY_NAME = "sans-serif-medium";
private InfoModel InfoModel;
private RateModel RateModel;
@BindView(R.id.shop_final_nested_scroll_view)
NestedScrollView nestedScrollView;
@BindView(R.id.shop_final_pending_txt)
TextView pendingDurationTxt;
@BindView(R.id.shop_final_rate_cond_rv)
RecyclerView rateCondRv;
@BindView(R.id.shop_final_description_txt)
TextView descriptionTxt;
@Inject
ToolsManager toolsManager;
RateConditionsAdapter adapter;
private String getParams;
public static ShopFinalTermsFragment newInstance(String getParams, InfoModel shopInfoModel, RateModel RateModel) {
ShopFinalTermsFragment fragment = new ShopFinalTermsFragment();
Bundle args = new Bundle();
args.putString(SHOP_GET_PARAMS, shopGetParams);
args.putSerializable(INFO_MODEL_KEY, shopInfoModel);
args.putSerializable(MODEL_KEY, userCashbackRateModel);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
this.GetParams = getArguments().getString(SHOP_GET_PARAMS);
this.InfoModel = (InfoModel) getArguments().getSerializable(INFO_MODEL_KEY);
this.RateModel = (RateModel) getArguments().getSerializable(RATE_MODEL_KEY);
}
}
@Override
protected void setupInOnCreateView() {
nestedScrollView.setVisibility(View.VISIBLE);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
conditionsTxt.setTypeface(Typeface.create(SANS_SERIF_FAMILY_NAME, Typeface.BOLD));
} else {
conditionsTxt.setTypeface(Typeface.create(SANS_SERIF_MEDIUM_FAMILY_NAME, Typeface.NORMAL));
}
}
@Override
protected void inject() {
ShopsComponent shopsComponent = DaggerShopsComponent.builder()
.applicationComponent(((BaseActivity) getActivity()).getApplicationComponent())
.build();
shopsComponent.inject(this);
}
public void setupWithData(InfoModel InfoModel, RateModel RateModel) {
//THIS METHOD IS COLLED FROM ACTIVITY'S onDataLoaded(InfoModel InfoModel, RateModel RateModel) method
setupShopInformation(shopInfoModel);
setCashBackRateModel(userCashbackRateModel);
}
}
您以错误的方式使用了依赖项。应该在片段上调用 setupWithData
的不是 activity,而应该是从 activity(或其他存储)获取数据的片段。这样,您将打破对最终未初始化的片段生命周期的依赖。
从服务器获取数据,将其存储在您需要的地方,然后从您的 activity 更新 UI。此时你要么显示 MyFragment1
,要么显示你的 TabLayout/ViewPager
。如果它是 TabLayout
或 ViewPager
,您所做的就是创建片段并将其添加到布局或相应的寻呼机适配器中。而已。您此时不设置数据。
现在,当您的内部片段填充到寻呼机适配器中时,它们将经历 onAttach
、onCreate
、onStart
和 onResume
生命周期方法。 onResume
是加载数据的好地方。您可以直接从片段访问它,也可以从出站 activity 获取它 - 取决于什么对您更有意义。如果您需要 activity 引用,您可以通过片段中的 getActivity()
方法访问它。
因此在该片段的 onResume
中,您将拥有类似的内容:
setupShopInformation((YourActivity) getActivity()).getShopInfoModel());
setCashBackRateModel((YourActivity) getActivity()).getUserCashbackRateModel());
尽管以某种状态存储它会更好 class。但这将是一个单独的问题。
祝你好运!