我使用ViewPager
编写了一个活动,该活动在执行AsyncTask
后填充。每个TestDataObject
都与相关的TestFragment
相关联。当屏幕旋转时,应用程序会因NullPointerException
内部onCreateView
方法而崩溃。我认为这是因为ViewPager
/适配器onSaveInstanceState
方法,onCreateView
尝试在数据不可用时加载AsyncTask
数据之前恢复数据。
我只能if
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 {
}
}
答案 0 :(得分:0)
我相信这是因为ViewPager / Adapter onSaveInstanceState 方法。 onCreateView尝试在异步任务之前恢复数据 数据尚不可用时的dataload。
这不是正在发生的事情(我假设你在mDataObject.toString();
得到了例外),即使AsyncTask
即时完成其工作,仍然会抛出异常。第一次运行应用程序后,ViewPager
将包含三个片段。当您转动手机时,Activity
将被销毁并再次重新创建。 ViewPager
将尝试重新创建其中的片段,但这次它将通过使用默认的空构造函数来实现(这就是为什么不应该使用非空构造函数来传递数据)。如您所见,第一次由适配器创建Fragment
时,它将由您getInstance
方法(也是您初始化mDataObject
的唯一点)创建传递TestDataObject
个对象。当ViewPager
重新初始化其片段时,该字段不也会被初始化。
如果TestDataObject
可以放在Bundle
中,那么您可以简单地调整getInstance
方法将一些参数传递给您的片段(因此数据字段将在{{{}时初始化1}}将重新创建它们)。我相信你已经看到了:
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
}
(如上所述),这样它就有足够的信息在重新创建时重新创建数据。