1. chibi929

    No comment

    chibi929
Changes in body
Source | HTML | Preview
@@ -1,218 +1,217 @@
ActivityとFragmentのライフサイクルを意識しなければならない状況で、
思っていたライフサイクルとは異なるフローで呼ばれていたため、
調査をしてみました。(主に破棄周り)
http://developer.android.com/guide/components/fragments.html
> The lifecycle of the activity in which the fragment lives directly affects the lifecycle of the fragment, such that each lifecycle callback for the activity results in a similar callback for each fragment. For example, when the activity receives onPause(), each fragment in the activity receives onPause().
上記を読んで、
Activityが `onPause()` を受け取ったときに Fragmentも `onPause()` を受け取る。となっていますが、
ActivityよりもFragmentのほうが短命のはずなので、
破棄時は `Fragment.onDestroy()` の後に `Activity.onDestroy()` となると思っていました。
※逆に起動時は `Activity.onCreate()` の後に `Fragment.onCreate()` となると思っていました。
# 前置き
まずは、公式リファレンスのライフサイクルのおさらい。
(画像を貼るだけ)
## Activityのライフサイクル
http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
![activity_lifecycle.png](https://qiita-image-store.s3.amazonaws.com/0/53393/7264706d-ccd7-b57a-3eca-cdf4c6675a3d.png)
## Fragmentのライフサイクル
http://developer.android.com/guide/components/fragments.html#Creating
![fragment_lifecycle.png](https://qiita-image-store.s3.amazonaws.com/0/53393/a23fa119-b41b-f7a2-b940-5ca1a79157e4.png)
# ライフサイクル調査
さて、ここからActivityとFragmentを使ったライフサイクルを調査していきます。
冒頭に記載した通り、主に破棄周りについて。
**環境**
* Android Studio: 1.3
* Mininum SDK: API 15 Android 4.0.3
**予想**
* `Fragment.onDestroyView()` -> `Fragment.onDestroy()` -> `Fragment.onDetach()` -> `Activity.onDestroy()`
**調査方法**
* Activityの起動から終了までのコールバックを追います。
**調査対象は2種類**
* `android.app.Activity` を継承したActivityに `android.app.Fragment` を追加する
* 便宜上 `AppActivity` , `AppFragment` とします。
* `android.support.v4.app.FragmentActivity` を継承したActivityに `android.support.v4.app.Fragment` を追加する
* 便宜上 `V4AppActivity` , `V4AppFragment` とします。
## ActivityとFragment
```java:AppActivityjava
public class AppActivity extends LifeCycleActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_app);
if (savedInstanceState == null) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.container, new AppFragment());
ft.commit();
}
}
}
```
※基底クラスの `LifeCycleActivity` は `Activity` を継承して各種コールバックのログを出力しているクラスです。
```java:AppFragment.java
public class AppFragment extends LifeCycleFragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
return inflater.inflate(R.layout.fragment_app, container, false);
}
}
```
※基底クラスの `LifeCycleFragment` は `android.app.Fragment` を継承して各種コールバックのログを出力しているクラスです。
```:logcat
// ここから起動処理
D/LifeCycleActivity( 3575): onCreate
D/LifeCycleFragment( 3575): onAttach
D/LifeCycleFragment( 3575): onCreate
D/LifeCycleFragment( 3575): onCreateView
D/LifeCycleFragment( 3575): onActivityCreated
D/LifeCycleActivity( 3575): onStart
D/LifeCycleFragment( 3575): onStart
D/LifeCycleActivity( 3575): onResume
D/LifeCycleFragment( 3575): onResume
// ここから終了処理
D/LifeCycleFragment( 3575): onPause
D/LifeCycleActivity( 3575): onPause
D/LifeCycleFragment( 3575): onStop
D/LifeCycleActivity( 3575): onStop
D/LifeCycleFragment( 3575): onDestroyView
D/LifeCycleFragment( 3575): onDestroy
D/LifeCycleFragment( 3575): onDetach
D/LifeCycleActivity( 3575): onDestroy
```
※ログはActivityの起動から終了までです。
予想通り、
起動処理は `Activity` -> `Fragment` の順
終了処理は `Fragment` -> `Activity` の順
## FragmentActivityとFragment
```java:V4AppActivity
public class V4AppActivity extends LifeCycleFragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_v4_app);
if (savedInstanceState == null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.container, new V4AppFragment());
ft.commit();
}
}
}
```
* 前者との違い
* 継承元が異なる( `extends Activity` が `extends FragmentActivity` に変わっている )
* `getFragmentManager()` が `getSupportFragmentManager()` に変わっている
※基底クラスの `LifeCycleFragmentActivity ` は `FragmentActivity` を継承して各種コールバックのログを出力しているクラスです。
```java:V4AppFragment
public class V4AppFragment extends LifeCycleV4Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
return inflater.inflate(R.layout.fragment_v4_app, container, false);
}
}
```
* 前者との違い
* 継承元が異なる( `extends android.app.Fragment` が `extends android.support.v4.app.Fragment` に変わっている )
※基底クラスの `LifeCycleV4Fragment ` は `android.support.v4.app.Fragment` を継承して各種コールバックのログを出力しているクラスです。
```:logcat
// ここから起動処理
D/LifeCycleFragmentActivity( 3575): onCreate
D/LifeCycleFragmentActivity( 3575): onStart
D/LifeCycleV4Fragment( 3575): onAttach
D/LifeCycleV4Fragment( 3575): onCreate
D/LifeCycleV4Fragment( 3575): onCreateView
D/LifeCycleV4Fragment( 3575): onActivityCreated
D/LifeCycleV4Fragment( 3575): onStart
D/LifeCycleFragmentActivity( 3575): onResume
D/LifeCycleV4Fragment( 3575): onResume
// ここから終了処理
D/LifeCycleFragmentActivity( 3575): onPause
D/LifeCycleV4Fragment( 3575): onPause
D/LifeCycleFragmentActivity( 3575): onStop
D/LifeCycleV4Fragment( 3575): onStop
D/LifeCycleFragmentActivity( 3575): onDestroy
D/LifeCycleV4Fragment( 3575): onDestroyView
D/LifeCycleV4Fragment( 3575): onDestroy
D/LifeCycleV4Fragment( 3575): onDetach
```
※ログはActivityの起動から終了までです。
ここが予想外でした!
起動処理も終了処理も `Activity` -> `Fragment` の順
# Activityの状態とFragmentのライフサイクル
色々なサイトを巡ってライフサイクルを確認しましたが、
下記に記載した参考サイトでもライフサイクルがマチマチだし、
以下のデベロッパーサイトの図を見ても、
-Activityのステートが `Destroyed` の時に、Fragmentの `onDestroyView()` , `onDestroy` , `onDetach()` となっているので、
-Activityの `onDestroy()` が来るタイミングは「Fragmentより前!」とか「Fragmentより後!」とかは無いのかなぁ。
+Activityのステートが `Destroyed` の時に、Fragmentの `onDestroyView()` , `onDestroy` , `onDetach()` となっているので、Activityの `onDestroy()` が来るタイミングは「Fragmentより前!」とか「Fragmentより後!」とかは無いのかなぁ。
今のところ Activity を使った場合のログの出力のされ方は毎回一定だし、
FragmentActivity を使った場合のログの出力のされ方も毎回一定で、
タイミングによって変化してるようには見えない。
http://developer.android.com/guide/components/fragments.html#Lifecycle
![activity_fragment_lifecycle.png](https://qiita-image-store.s3.amazonaws.com/0/53393/7a1ba6dd-13d2-8491-08bb-56da5d621235.png)
今回は `API 15: Android 4.0.3 IceCreamSandwich` でプロジェクトを作成したからFragmentActivityが継承されたMainActivityが出来たのだと思われる。
`API 22: Android 5.1 Lollipop` では、どうやらデフォルトでActivityが継承されるらしい。
きっと `Android 6.0 Marshmallow(マシュマロ)` でもActivityが継承されたものがデフォルトで作成される。
-~~(実は `API 22(Lillipop)` や `API 23(Marshmallow)` では、今回調査対象した2種類両方とも同じコールバックだったりして...)~~
+~~(実は `API 22(Lillipop)` や `API 23(Marshmallow)` では、今回調査対象した2種類両方とも同じコールバックだったりして...)~~
調べてみると、 `API 22(Lillipop)` や `API 23(Marshmallow)` では、
-デフォルトでは `appcompat-v7` とか `support-v4` 使われていませんでした。
+デフォルトでは `appcompat-v7` とか `support-v4` は、使われていませんでした。
但し、自分でライブラリを追加して使うことができるので、試してみたところ上記調査結果通りのログになりました。
どちらにしても使い方に気を付けなければ!!
# 最後に
今回の調査で作ったサンプルアプリです。
https://github.com/chibi929/AndroidLifeCycle
# 参考サイト
http://techbooster.org/android/environment/17001/
http://qiita.com/suzukihr/items/90a93e79dc67c585de75
http://yuki312.blogspot.jp/2012/02/androidfragmentactivity.html