Android Fragment で onCreateView が呼ばれずに onDestroy が呼ばれることはありますか


自作のアプリを実機へインストールしています。  
端末の電源ボタンを押し休止モードから復帰したところ、例外が発生し落ちたのでこの問題を修正したいのですが、原因がわかりません。

以下のようなコードで、 `onDestroy` 中の `myfield` が `null` であるという例外が発生していました。  
(crashlyticsが拾ったスタックトレースを最後に添付しています。)

[code]

    
    public class MyFragment extends Fragment {
    
        private MyClass myfield;
    
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                                 @Nullable Bundle savedInstanceState) {
    ...
            myfield = new MyClass();
    ...
            return view;
        }
    
        @Override
        public void onDestroyView() {
            super.onDestroyView();
            myfield.onDestroyView();
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            myfield.onDestroy();
        }
    }
    
    
[/code]

`myfield`への代入はこの1箇所のみであり、`onCreateView`が実行されたのであれば`null`になることはないはずだと考えております。  
また、コードを変更し`onCreateView`内で例外が発生するようにしてみたところ、`onDestroy`は呼ばれないことも確認しました。  
(追記)加えて、`onDestroyView`内でも`myfield`のメソッドを呼ぶ実装をしておりますが、ここでは例外が発生していません(そもそも呼ばれていない？)。

休止から復帰したタイミング、というところになにか通常には無いフローがあるような気もするのですが、 `onCreateView` が呼ばれずに
`onDestroy` が呼ばれるような条件はあるのでしょうか。  
また、ありえる場合、どのような記述で対応するのが一般的なのでしょうか。

[code]

    java.lang.RuntimeException: Unable to destroy activity {my.app/my.app.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void my.app.MyClass.onDestroy()' on a null object reference
           at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3706)
           at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3724)
           at android.app.ActivityThread.access$1400(ActivityThread.java:151)
           at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1357)
           at android.os.Handler.dispatchMessage(Handler.java:102)
           at android.os.Looper.loop(Looper.java:135)
           at android.app.ActivityThread.main(ActivityThread.java:5254)
           at java.lang.reflect.Method.invoke(Method.java)
           at java.lang.reflect.Method.invoke(Method.java:372)
           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
    Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void my.app.MyClass.onDestroy()' on a null object reference
           at my.app.MyFragment.onDestroy(MyFragment.java:83)
           at android.support.v4.app.Fragment.performDestroy(Fragment.java:2006)
           at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1076)
           at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1126)
           at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1108)
           at android.support.v4.app.FragmentManagerImpl.dispatchDestroy(FragmentManager.java:1954)
           at android.support.v4.app.FragmentActivity.onDestroy(FragmentActivity.java:313)
           at android.support.v7.app.ActionBarActivity.onDestroy(ActionBarActivity.java:169)
           at my.app.MainActivity.onDestroy(MainActivity.java:97)
           at android.app.Activity.performDestroy(Activity.java:6169)
           at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1141)
           at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3693)
           at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3724)
           at android.app.ActivityThread.access$1400(ActivityThread.java:151)
           at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1357)
           at android.os.Handler.dispatchMessage(Handler.java:102)
           at android.os.Looper.loop(Looper.java:135)
           at android.app.ActivityThread.main(ActivityThread.java:5254)
           at java.lang.reflect.Method.invoke(Method.java)
           at java.lang.reflect.Method.invoke(Method.java:372)
           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
    
[/code]




再現しました。

## 前提

`FragmentPagerAdapter`は次のように、インデックスを伝えて各ページを生成してるとします。

[code]

    public class MyPagerAdapter extends FragmentPagerAdapter {
        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
        }
    
        @Override
        public Fragment getItem(int i) {
            return ItemFragment.newInstance(i);
        }
    
        @Override
        public int getCount() {
            return 10;
        }
    }
    
[/code]

この状態で、１ページだけスワイプで切り替えた状態で、ホームボタンで中断します。当然ですがActivityは保持しない設定にしておきます。

LogCatを貼って挙動を説明します。

[code]

    07-28 22:22:24.977    8859-8859/com.mokelab.pager V/Item﹕ onDestroy index=0
    07-28 22:22:24.977    8859-8859/com.mokelab.pager V/Item﹕ onDestroy index=1
    07-28 22:22:24.978    8859-8859/com.mokelab.pager V/Item﹕ onDestroy index=2
    07-28 22:22:24.978    8859-8859/com.mokelab.pager V/Item﹕ onDestroy index=3
    07-28 22:22:31.172    8859-8859/com.mokelab.pager V/Item﹕ onCreateView index=1
    07-28 22:22:31.173    8859-8859/com.mokelab.pager V/Item﹕ onCreateView index=2
    07-28 22:22:31.174    8859-8859/com.mokelab.pager V/Item﹕ onCreateView index=3
    07-28 22:22:35.162    8859-8859/com.mokelab.pager V/Item﹕ onDestroy index=0
    07-28 22:22:35.162    8859-8859/com.mokelab.pager V/Item﹕ onDestroy index=1
    07-28 22:22:35.162    8859-8859/com.mokelab.pager V/Item﹕ onDestroy index=2
    07-28 22:22:35.163    8859-8859/com.mokelab.pager V/Item﹕ onDestroy index=3
    
[/code]

まず、一度でも`attach`された`Fragment`の`onDestroy()`が呼ばれているのがわかります。なので、`index=0`も`onDestroy()`が呼ばれています。

そしてアプリスイッチで再開すると、`index=0`の`Fragment`の`View`は生成する必要のない位置にいるので、1〜3の`onCreateView()`が呼ばれていますね。

そしてこの状態で再度ホームボタンで中断すると、やはり`index=0`の`Fragment`は復元されているので、`onDestroy()`が呼ばれています。




再現しました。

## 前提

`FragmentPagerAdapter`は次のように、インデックスを伝えて各ページを生成してるとします。

[code]

    public class MyPagerAdapter extends FragmentPagerAdapter {
        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
        }
    
        @Override
        public Fragment getItem(int i) {
            return ItemFragment.newInstance(i);
        }
    
        @Override
        public int getCount() {
            return 10;
        }
    }
    
[/code]

この状態で、１ページだけスワイプで切り替えた状態で、ホームボタンで中断します。当然ですがActivityは保持しない設定にしておきます。

LogCatを貼って挙動を説明します。

[code]

    07-28 22:22:24.977    8859-8859/com.mokelab.pager V/Item﹕ onDestroy index=0
    07-28 22:22:24.977    8859-8859/com.mokelab.pager V/Item﹕ onDestroy index=1
    07-28 22:22:24.978    8859-8859/com.mokelab.pager V/Item﹕ onDestroy index=2
    07-28 22:22:24.978    8859-8859/com.mokelab.pager V/Item﹕ onDestroy index=3
    07-28 22:22:31.172    8859-8859/com.mokelab.pager V/Item﹕ onCreateView index=1
    07-28 22:22:31.173    8859-8859/com.mokelab.pager V/Item﹕ onCreateView index=2
    07-28 22:22:31.174    8859-8859/com.mokelab.pager V/Item﹕ onCreateView index=3
    07-28 22:22:35.162    8859-8859/com.mokelab.pager V/Item﹕ onDestroy index=0
    07-28 22:22:35.162    8859-8859/com.mokelab.pager V/Item﹕ onDestroy index=1
    07-28 22:22:35.162    8859-8859/com.mokelab.pager V/Item﹕ onDestroy index=2
    07-28 22:22:35.163    8859-8859/com.mokelab.pager V/Item﹕ onDestroy index=3
    
[/code]

まず、一度でも`attach`された`Fragment`の`onDestroy()`が呼ばれているのがわかります。なので、`index=0`も`onDestroy()`が呼ばれています。

そしてアプリスイッチで再開すると、`index=0`の`Fragment`の`View`は生成する必要のない位置にいるので、1〜3の`onCreateView()`が呼ばれていますね。

そしてこの状態で再度ホームボタンで中断すると、やはり`index=0`の`Fragment`は復元されているので、`onDestroy()`が呼ばれています。

