Android ViewPager和Activity在Activity onDestroy onCreate之后以片段形式重新创建/持久化数据
我用Android ViewPager和Activity在Activity onDestroy onCreate之后以片段形式重新创建/持久化数据,android,android-fragments,android-viewpager,Android,Android Fragments,Android Viewpager,我用ViewPager编写了一个活动,它在执行AsyncTask后填充。每个TestDataObject都绑定到相关的TestFragment。当屏幕旋转时,由于NullPointerException内部onCreateView方法,应用程序会崩溃。我相信这是因为ViewPager/AdapteronSaveInstanceState方法,onCreateView在数据还不可用时尝试在AsyncTask数据加载之前恢复数据 如果onCreateView代码,我就可以,但我觉得这不是一个正确的解
ViewPager
编写了一个活动,它在执行AsyncTask
后填充。每个TestDataObject
都绑定到相关的TestFragment
。当屏幕旋转时,由于NullPointerException
内部onCreateView
方法,应用程序会崩溃。我相信这是因为ViewPager
/AdapteronSaveInstanceState
方法,onCreateView
在数据还不可用时尝试在AsyncTask
数据加载之前恢复数据
如果onCreateView代码,我就可以,但我觉得这不是一个正确的解决方案,因为ViewPager中的片段数量可能会有所不同,因此它可能会做一些不必要的工作:恢复更改后的ViewPager内容,然后替换为初始内容。在这种情况下,onSaveInstanceState似乎过于有害。大概,我可以扩展ViewPager或Adapter来取消保存过程——我也觉得这很奇怪
你有更好的建议吗
public class MainActivity extends LoggerActivity {
private ArrayList<TestDataObject> mDataObjects = new ArrayList<MainActivity.TestDataObject>();
private ViewPager mViewPager;
private TestFragmentAdapter mViewPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPagerAdapter = new TestFragmentAdapter(
getSupportFragmentManager(), mDataObjects);
mViewPager.setAdapter(mViewPagerAdapter);
new TestAsyncTask().execute();
}
private class TestAsyncTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
mDataObjects.add(new TestDataObject());
mDataObjects.add(new TestDataObject());
mDataObjects.add(new TestDataObject());
mViewPagerAdapter.notifyDataSetChanged();
}
}
public static class TestFragment extends Fragment {
private TestDataObject mDataObject;
public static TestFragment getInstance(TestDataObject obj) {
TestFragment f = new TestFragment();
f.mDataObject = obj;
return f;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// layout.find...
mDataObject.toString();
return inflater.inflate(R.layout.fragment_test, null, false);
}
}
public static class TestFragmentAdapter extends FragmentStatePagerAdapter {
private List<TestDataObject> mDataObjects;
public TestFragmentAdapter(FragmentManager fm, List<TestDataObject> objs) {
super(fm);
mDataObjects = objs;
}
@Override
public Fragment getItem(int position) {
return TestFragment.getInstance(mDataObjects.get(position));
}
@Override
public int getCount() {
return mDataObjects == null ? 0 : mDataObjects.size();
}
}
public static class TestDataObject {
}
}
public类MainActivity扩展了LoggerActivity{
private ArrayList mDataObjects=new ArrayList();
私有视图寻呼机mViewPager;
私有TestFragmentAdapter mViewPagerAdapter;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager=(ViewPager)findViewById(R.id.pager);
mViewPagerAdapter=新的TestFragmentAdapter(
getSupportFragmentManager(),mDataObjects);
setAdapter(mViewPagerAdapter);
new TestAsyncTask().execute();
}
私有类TestAsyncTask扩展了AsyncTask{
@凌驾
受保护的Void doInBackground(Void…参数){
试一试{
时间单位。秒。睡眠(3);
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
返回null;
}
@凌驾
受保护的void onPostExecute(void结果){
super.onPostExecute(结果);
添加(新的TestDataObject());
添加(新的TestDataObject());
添加(新的TestDataObject());
mViewPagerAdapter.notifyDataSetChanged();
}
}
公共静态类TestFragment扩展了片段{
私有TestDataObject-mDataObject;
公共静态TestFragment getInstance(TestDataObject obj){
TestFragment f=新的TestFragment();
f、 mDataObject=obj;
返回f;
}
@凌驾
创建视图上的公共视图(布局、充气机、视图组容器、,
Bundle savedInstanceState){
//布局。查找。。。
mDataObject.toString();
返回充气机。充气(R.layout.fragment_测试,空,假);
}
}
公共静态类TestFragmentAdapter扩展了FragmentStatePagerAdapter{
私有列表对象;
公共TestFragmentAdapter(FragmentManager fm,列表objs){
超级(fm);
mDataObjects=objs;
}
@凌驾
公共片段getItem(int位置){
返回TestFragment.getInstance(mDataObjects.get(position));
}
@凌驾
public int getCount(){
返回mDataObjects==null?0:mDataObjects.size();
}
}
公共静态类TestDataObject{
}
}
我相信这是因为SaveInstanceState上的ViewPager/适配器
方法。onCreateView尝试在异步任务之前还原数据
数据尚未可用时加载数据
事实并非如此(我假设您在mDataObject.toString();
处获得异常),即使AsyncTask
会立即完成其工作,也会引发异常。第一次运行应用程序后,ViewPager
将包含三个片段。当您打开手机时,活动
将被销毁并重新创建。ViewPager
将尝试重新创建其中的片段,但这次它将使用默认的空构造函数(这就是为什么不应该使用非空构造函数传递数据)。如您所见,适配器第一次创建片段
时,它将由getInstance
方法创建(这也是初始化mDataObject
的唯一点),您将TestDataObject
对象传递到该方法。当ViewPager
重新初始化其片段时,该字段也将不初始化
如果可以将TestDataObject
放入Bundle
中,那么您可以简单地调整getInstance
方法,将一些参数传递给片段(因此当ViewPager
重新创建它们时,数据字段将被初始化)。我相信你已经看到:
public static TestFragment getInstance(TestDataObject obj) {
TestFragment f = new TestFragment();
// f.mDataObject = obj; <- don't do this
// if possible
Bundle args = new Bundle();
args.put("data", obj); // only if obj can be put in a Bundle
f.setArguments(args);
return f;
}
private TestDataObject mDataObject;
@Override
public void onCreate(Bundle savedInstance) {
mDataObject = getArguments().get("data"); // again, depends on your TestDataObject
}
publicstatictestfragmentgetinstance(testdataobjectobj){
TestFragment f=新的TestFragment();
//f.mDataObject=obj;我想您需要添加理解代码所需的部分代码,例如onSavedInstance方法。我对onSaveInstanceState没有任何处理。是组件本身试图保存当前视图状态。我可能应该研究有不同的方法来持久化状态(旋转只是需要保持状态的一个示例)。一种方法是实现onSaveInstanceState并在以后检索数据。另一种方法只是你的链接建议的方式,不如实现你自己的onSaveInstanceState灵活。如果我没记错,如果你使用这种方法,应用程序不会根据当前的新方向查找新布局,你应该这样做你的