自上周以来,我一直在努力解决这个错误。这是:
public class MainActivity extends FragmentActivity implements ActionBar.TabListener {
AppSectionsPagerAdapter mAppSectionsPagerAdapter;
ViewPager mViewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAppSectionsPagerAdapter = new AppSectionsPagerAdapter(getSupportFragmentManager(), getApplicationContext());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mAppSectionsPagerAdapter);
...
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.refresh:
mAppSectionsPagerAdapter.onRefresh();
return true;
...
}
public class AppSectionsPagerAdapter extends FragmentPagerAdapter {
private ArrayList<Fragment> fragmentList;
private MainSectionFragment f1, f2;
private SelectedSectionFragment f3;
public AppSectionsPagerAdapter(FragmentManager fm, Context c) {
f3 = new SelectedSectionFragment();
f2 = new MainSectionFragment();
f1 = new MainSectionFragment();
fragmentList = new ArrayList<Fragment>();
fragmentList.add(f1);
fragmentList.add(f2);
fragmentList.add(f3);
...
}
public void onRefresh(){
MainSectionFragment fragment = (MainSectionFragment)fragmentList.get(0);
fragment.fetchList();
}
...
}
public class MainSectionFragment extends Fragment implements CallbackListener {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//some initialization
c = getActivity().getApplicationContext(); // tested and it gets initialized
System.out.println(""+hashCode());
...
}
void fetchList() {
System.out.println(""+hashCode());
android.support.v4.app.FragmentManager manager = getActivity().getSupportFragmentManager();
...
}
}
我从ActivityMain
导航,它就死了。当我回来时,列表可以垂直和水平滚动。如果我单击刷新按钮NullPointerException
出现。我调试了这个程序。从SettingsActivity返回时会调用OnCreateView()
,但当我点击“刷新”按钮时,MainSectionFragment
的每个字段都会变为 null 。
异常前打印的哈希码:
05-25 01:54:37.190: I/System.out(5982): 1091848056 //onCreateView()
05-25 01:54:42.680: I/System.out(5982): 1091574888 //fetchList()
无法理解为什么这些对象会有所不同。
如果我的问题不明确,请告诉我。
更新1
我已经检查过“不要保持活动&#39;开发工具中的选项。我已经确认从SettingsActivity返回后调用了MainActivity onCreate
更新2
转到SettingsActivity 分离片段。从SettingsActivity返回 再次附加片段。
答案 0 :(得分:3)
修改强>
尽管最初的答案非常接近正确回答,但我想编辑以便为案例带来一些知识。
Fragment堆栈(在某种观点下)与活动非常相似。因为片段也会被框架自动销毁并重新创建,并通过绕过回调传递的Bundles
保存状态(savedInstanceState)。
所以正在发生的事情是,即使正在重新创建活动并调用新的适配器,在向ViewPager提供片段时,适配器首先将findFragmentByTag
调用到FragmentManager
这样就可以重新创建保存的状态,如果没有,则只调用public Fragment getItem(int position)
。
因此,您在屏幕上看到的片段不是AppSectionsPagerAdapter
构造函数中创建的对象。那些碎片从未使用过。
请记住,尽管乍一看听起来很奇怪,但这是一个非常理想的功能。例如:假设片段上有一个EditText
,用户用一些文本填充它。当碎片被破坏时,该值将保存在Bundle
上,并且在恢复时,该值仍然存在。
原始回答:
&#34;无法理解为什么这些对象不同。&#34;因为这就是框架的运作方式。片段是可以由框架销毁/重新创建的对象。
99%的可能性是:
refresh
按钮修复代码的最直接(也更清晰)方法是让Fragment处理菜单,只需将其简单地放入片段代码中,然后从活动中删除菜单内容:
onCreate(Bundle savedInstance){
setHasOptionsMenu(true);
}
onOptionsItemSelected(MenuItem item){
if(item.getItemId() == R.id.refresh){
.. do your stuff here
return true;
} else return super.refresh(item);
}
如果由于某种原因你没有解释你真的必须处理活动中的菜单还有其他选择:
例如:您可以从活动中发送LocalBroadcast
并让片段在onResume / onPause期间注册/取消注册BroadcastReceiver
或另一个好方法:FragmentPagerAdater
使用以下方法为FragmentManager
创建片段TAG:
private static String makeFragmentName(int viewId, long id) {
return "android:switcher:" + viewId + ":" + id;
}
然后您可以将其添加到您的活动中并致电:
(MainSectionFragment)getSupportFragmentManager().
findFragmentByTag(
makeFragmentName(R.id.pager, mAppSectionsPagerAdapter.getItemId(0)))
.fetchList();
答案 1 :(得分:1)
我认为如果您保留实例,它可能会解决问题。
要在您的oncreateview中执行此操作,请添加以下行:
setRetainInstance(true);