未添加片段(不一致的崩溃)
Fragment not added (inconsistent crash)
在我的 MainActivity
中,我有:
@Override
protected void onResume() {
super.onResume();
checkForCrashes();
checkForTutorial();
checkForUpdates();
setStore();
setup();
}
在setup()
中,我在回调中调用initializeTabs()
:
protected void setup() {
final Store s = getStore();
setBackground();
if (s == null) {
unauthorizedHandler();
return;
}
final Context mainActivity = this;
fragments = getTabFragments();
StoresController.getStoreDetails(s, mainActivity, new Callback<StoreDetailDecorator>() {
@Override
public void success(StoreDetailDecorator storeDetailDecorator, Response response) {
s.prettyName = storeDetailDecorator.store.pretty_name;
s.save();
Log.v(TAG, s.prettyName);
TextView toolbar_label = (TextView)findViewById(R.id.toolbar_label);
toolbar_label.setText(MainActivity.getTruncatedMenuName(s.name()));
SummaryTab t1 = (SummaryTab)fragments.get(0);
t1.notifier = (SummaryTabLoadingNotifier)mainActivity;
initializeTabs(s, fragments);
t1.populateReport();
}
}
}
public void initializeTabs(Store s, List<Fragment> fragments ) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager(), getTabTitles(), fragments);
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setOffscreenPageLimit(2);
pager.setAdapter(adapter);
}
最后一行对某些客户来说是崩溃的。
java.lang.IllegalStateException: Fragment InfoTab{1bcb80f} is not currently in the FragmentManager
但不是每次都是。为什么有时会出现这种情况?与未连接的片段有关?我读了一些关于检查片段 isAdded()
的内容,但那是为了检查片段是否添加到 Activity。我正在使用 FragmentStatePagerAdapter
:
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private CharSequence[] titles;
private List<Fragment> fragmentList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager fragmentManager, CharSequence titles[], List<Fragment> fragmentList) {
super(fragmentManager);
this.titles = titles;
this.fragmentList = fragmentList;
}
@Override
public android.support.v4.app.Fragment getItem(int position) {
return fragmentList.get(position);
}
@Override
public CharSequence getPageTitle(int position) { return titles[position]; }
@Override
public int getCount() { return fragmentList.size(); }
@Override
public Parcelable saveState() {
return null;
}
}
可以saveState(){ return null;}
吗?据我了解,这是为了确保每次都刷新视图。
onResume()
每次 activity returns 到前台时都会被调用。
例如,如果您的某个用户按下主页按钮并 returns 进入您的应用程序,那么 getStoreDetails()
将被再次调用,您将创建一个新的适配器(使用相同的旧适配器片段列表)当结果到达时。
你应该实例化你的片段,创建一个适配器并只用适配器填充你的 viewpager
一次(onCreate()
就是那个地方)。
当新数据来自 getStoreDetails()
时,只需使用新数据更新已添加的片段。
这是因为您将在 saveState()
返回 null
。您不应尝试覆盖此行为。
但即使你出于某种原因想要这样做,你也必须覆盖 public void restoreState(Parcelable state, ClassLoader loader)
以避免崩溃,因为该方法依赖于保存在 saveState()
.
中的数据
但我建议您根本不要覆盖它,而是解释您想要在那里实现的目标。
在我的 MainActivity
中,我有:
@Override
protected void onResume() {
super.onResume();
checkForCrashes();
checkForTutorial();
checkForUpdates();
setStore();
setup();
}
在setup()
中,我在回调中调用initializeTabs()
:
protected void setup() {
final Store s = getStore();
setBackground();
if (s == null) {
unauthorizedHandler();
return;
}
final Context mainActivity = this;
fragments = getTabFragments();
StoresController.getStoreDetails(s, mainActivity, new Callback<StoreDetailDecorator>() {
@Override
public void success(StoreDetailDecorator storeDetailDecorator, Response response) {
s.prettyName = storeDetailDecorator.store.pretty_name;
s.save();
Log.v(TAG, s.prettyName);
TextView toolbar_label = (TextView)findViewById(R.id.toolbar_label);
toolbar_label.setText(MainActivity.getTruncatedMenuName(s.name()));
SummaryTab t1 = (SummaryTab)fragments.get(0);
t1.notifier = (SummaryTabLoadingNotifier)mainActivity;
initializeTabs(s, fragments);
t1.populateReport();
}
}
}
public void initializeTabs(Store s, List<Fragment> fragments ) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager(), getTabTitles(), fragments);
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setOffscreenPageLimit(2);
pager.setAdapter(adapter);
}
最后一行对某些客户来说是崩溃的。
java.lang.IllegalStateException: Fragment InfoTab{1bcb80f} is not currently in the FragmentManager
但不是每次都是。为什么有时会出现这种情况?与未连接的片段有关?我读了一些关于检查片段 isAdded()
的内容,但那是为了检查片段是否添加到 Activity。我正在使用 FragmentStatePagerAdapter
:
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private CharSequence[] titles;
private List<Fragment> fragmentList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager fragmentManager, CharSequence titles[], List<Fragment> fragmentList) {
super(fragmentManager);
this.titles = titles;
this.fragmentList = fragmentList;
}
@Override
public android.support.v4.app.Fragment getItem(int position) {
return fragmentList.get(position);
}
@Override
public CharSequence getPageTitle(int position) { return titles[position]; }
@Override
public int getCount() { return fragmentList.size(); }
@Override
public Parcelable saveState() {
return null;
}
}
可以saveState(){ return null;}
吗?据我了解,这是为了确保每次都刷新视图。
onResume()
每次 activity returns 到前台时都会被调用。
例如,如果您的某个用户按下主页按钮并 returns 进入您的应用程序,那么 getStoreDetails()
将被再次调用,您将创建一个新的适配器(使用相同的旧适配器片段列表)当结果到达时。
你应该实例化你的片段,创建一个适配器并只用适配器填充你的 viewpager
一次(onCreate()
就是那个地方)。
当新数据来自 getStoreDetails()
时,只需使用新数据更新已添加的片段。
这是因为您将在 saveState()
返回 null
。您不应尝试覆盖此行为。
但即使你出于某种原因想要这样做,你也必须覆盖 public void restoreState(Parcelable state, ClassLoader loader)
以避免崩溃,因为该方法依赖于保存在 saveState()
.
但我建议您根本不要覆盖它,而是解释您想要在那里实现的目标。