0

が実行されたViewPager後に入力される を使用してアクティビティを作成しました。AsyncTaskそれぞれTestDataObjectが関連する に関連付けられていますTestFragmentNullPointerException画面を回転させると、内部onCreateViewメソッドによりアプリケーションがクラッシュします。これはViewPager/AdapteronSaveInstanceStateメソッドが原因で、データがまだ利用できない場合onCreateViewに、データのロード前にデータを復元しようとするためだと思います。AsyncTask

私はifonCreateViewコードだけでできましたが、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 /AdapteronSaveInstanceStateメソッドが原因だと思います。onCreateViewは、データがまだ利用できない場合、asynctaskデータロードの前にデータを復元しようとします。

それは起こっていることではありません(私はあなたがで例外を取得すると仮定していますmDataObject.toString();)、たとえAsyncTaskその仕事を即座に終了したとしても、例外はスローされます。アプリの最初の実行後、ViewPager3つのフラグメントが含まれます。あなたが電話を回すとき、それは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 
}

もう1つのアプローチは、(上記のように)最小量のデータをFragment(上記のように)渡すことです。これにより、データが再作成されるたびにデータを再作成するのに十分な情報が得られます。

于 2013-02-15T13:56:04.633 に答える