透明Activity生命周期变化

December 16, 2016

最近重看《Android开发艺术探索》一书,其中第3页 Activity 生命周期 onPauseonResume 过程的确如作者所说“在一般的开发中用不上”,但是作为开发者还是有研究的必要。

onResume 的状态是 Activity 前台可见正在活动,onPause 是置于前台可见停止活动。从后者到前者的变化场景,可以通过一个透明的 Dialog 弹出遮蔽 MainActivity 重现。

不过,这是个“特殊”的 Dialog。一般 Dialog 弹出时,背景可见 MainActivity 依然是 onResume,表明这个 Activity 的生命周期并没有因为这个 Dialog 的弹出而变化。

但是,我们使用 Activity 实现 Dialog 时,由于是 MainActivity 启动 DialogActivity,所以 MainActivity 生命周期必然会变化。

MainActivity.java代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.btn_dialog).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent i = new Intent(MainActivity.this, DialogActivity.class);
                startActivity(i);
            }
        });
        System.out.println("onCreate");
    }
    
    // 实现所有生命周期方法Log
    @Override
    protected void onStart() {
        super.onStart();
        System.out.println("onStart");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        System.out.println("onRestart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        System.out.println("onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        System.out.println("onPause");
    }

    @Override
    protected void onStop() {
        super.onStop();
        System.out.println("onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        System.out.println("onDestroy");
    }
}

MainActivity.java对应activity_main.xml

Button 只是用来启动 Dialog_Activity

1
2
3
4
5
6
7
8
9
10
11
12
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn_dialog"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />
</RelativeLayout>

DialogActivity.java代码

1
2
3
4
5
6
7
8
9
10
11
12
13
public class DialogActivity extends Activity {
    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test_dialog);
        // 这里图个方便直接给findViewById加监听
        findViewById(R.id.returnButton).setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                DialogActivity.this.finish();
            }
        });
    }
}

test_dialog.xml

1
2
3
4
5
6
7
8
9
10
11
12
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/returnButton"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="点击退出"/>

</LinearLayout>

AndroidManifest.xml

注意: DialogActivity 使用主题 @android:style/Theme.Dialog,不然无法实现上述生命周期。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.phantomvk.exampleapp">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".DialogActivity"
            android:theme="@android:style/Theme.Dialog"/>
    </application>

</manifest>

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// MainActivity到可见可操作的三个周期变化
12-16 23:59:35.806 7477-7477/com.phantomvk.exampleapp I/System.out: onCreate
12-16 23:59:35.811 7477-7477/com.phantomvk.exampleapp I/System.out: onStart
12-16 23:59:35.811 7477-7477/com.phantomvk.exampleapp I/System.out: onResume

// 点击Button后,MainActivity仅仅是暂停(onPause),没有停止(onStop)
12-16 23:59:50.731 7477-7477/com.phantomvk.exampleapp I/System.out: onPause

// 在DialogActivity里面退出,MainActivity状态变为onResume
12-17 00:00:00.161 7477-7477/com.phantomvk.exampleapp I/System.out: onResume

// 退出应用: onPause -> onStop -> onDestroy
12-17 00:00:30.576 7477-7477/com.phantomvk.exampleapp I/System.out: onPause
12-17 00:00:31.151 7477-7477/com.phantomvk.exampleapp I/System.out: onStop
12-17 00:00:31.151 7477-7477/com.phantomvk.exampleapp I/System.out: onDestroy

上述代码已经成功重现 onPause -> onResume。运行截图如下

img