0

我用 写了一个活动ViewPager,它在 anAsyncTask执行后被填充。每个TestDataObject都与相关的TestFragment. 当屏幕旋转时,应用程序由于NullPointerException内部onCreateView方法而崩溃。我相信这是因为ViewPager/AdapteronSaveInstanceState方法,当数据尚不可用时,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 {
    }
}
4

1 回答 1

0

我相信这是因为 ViewPager/Adapter onSaveInstanceState 方法。当数据尚不可用时,onCreateView 会尝试在异步任务数据加载之前恢复数据。

这不是正在发生的事情(我假设你在 处得到异常mDataObject.toString();),即使AsyncTask它会立即完成它的工作,异常仍然会被抛出。应用程序第一次运行后,其中ViewPager将包含三个片段。当您转动手机时,Activity它将被销毁并重新创建。将ViewPager尝试重新创建其中的片段,但这次它将使用默认的空构造函数来完成(这就是为什么你不应该使用非空构造函数来传递数据)。如您所见,第一次Fragment由适配器创建时,它将由您传递对象的getInstance方法(这也是您初始化的唯一点)创建。当重新初始化其片段时,该字段将mDataObjectTestDataObjectViewPager也不会被初始化。

如果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 
}

另一种方法是将最少量的数据传递给Fragment(如上),以便它有足够的信息来在重新创建数据时重新创建它的数据。

于 2013-02-15T13:56:04.633 回答