Android开发艺术探索读书笔记(第1章 Activity的生命周期和启动模式)

1.onStart和onResume,onPause和onStop从描述上来说差不多,对我们来说有什么实质性的不同?
onStart和onStop是从Activity是否可见这个角度来区别的,onResume和onStop是从Activity是否位于前台来区分的。在实际使用中没有明显区别。

2.从A Activity启动B Activity,生命周期如下
A onPause->B onCreate->B onStart -> B onResume-> A onStop
再次返回A,生命周期如下
B onPause->A onRestart -> A onStart-> A onResume->B onStop

规律如下:当前Activity的onPause总是先执行,onStop总是在下一个Activity的onResume之后执行。

3.onPause和onStop都不能执行耗时操作,尤其是onPause,这意味着我们应该在onStop中做操作。

4.默认情况下,屏幕旋转会销毁当前Activity,然后重建,声明周期如下
Android开发艺术探索读书笔记(第1章 Activity的生命周期和启动模式)_第1张图片
如何防止Activity被销毁重建,
在清单文件中配置Activity

 <activity android:name=".MainActivity" android:configChanges="orientation|screenSize">

这样当屏幕旋转时Activity不会被销毁重建,而是调用onConfigurationChanged方法

5.Activity状态的保存
Android开发艺术探索读书笔记(第1章 Activity的生命周期和启动模式)_第2张图片

onSaveInstanceState会在onStop之前调用,onRestoreInstanceState会在onResume之前调用,和onStart以及onPause的顺序不定。

6.onCreate和onRestoreInstanceState都可以用来保存数据,区别是一旦onRestoreInstanceState被调用,参数一定不为空,官方建议是在onRestoreInstanceState恢复数据

7.onRestoreInstanceState调用的前提是Activity确实被销毁了,当我们按HOME键把当前Activity置于后台时,此时的生命周期方法如下
Android开发艺术探索读书笔记(第1章 Activity的生命周期和启动模式)_第3张图片

我们可以看到,onRestoreInstanceState没有被调用,因为Activity并没有被销毁,所以说这两个方法不一定是成对出现的。

启动模式

1.使用非Activity的Context启动Activity,会报错,

Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

这是因为非Activity的Context没有任务栈的概念,解决这个问题的办法是为Activity指定FLAG_ACTIVITY_NEW_TASK

TaskAffinity属性主要和singleTask和allowTaskReparenting属性结合使用,默认的taskAffinity使用的是Application的taskAffinity,也就是包名。

allowTaskReparenting解释:
应用A的Activity A 启动了应用B的Activity B,如果此Activity的allowTaskReparenting属性为true,当再次启动应用B时,显示的是Activity B,而不是应用B的主页面,因为Activity B的taskAffinity是和应用B一样的。

如何查看当前正在运行的Activity,在命令窗口输入下面的命令

adb shell dumpsys activitys

然后会打印出一大堆信息,我们找到ACTIVITY MANAGER ACTIVITIES,内容如下

ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):
  Stack #6:
    Task id #270
      TaskRecord{12ee53d #270 A=com.example.signatureapp U=0 sz=2}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.signatureapp/.MainActivity bnds=[60,776][180,896] (has extras) }
        Hist #1: ActivityRecord{3a99839 u0 com.example.app/.SecondActivity t270}
          Intent { act=com.lxn.test cmp=com.example.app/.SecondActivity }
          ProcessRecord{bf1aa06 2197:com.example.app/u0a62}
        Hist #0: ActivityRecord{9d6631b u0 com.example.signatureapp/.MainActivity t270}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.signatureapp/.MainActivity bnds=[60,776][180,896] (has extras) }
          ProcessRecord{4fe6132 2172:com.example.signatureapp/u0a61}

    Running activities (most recent first):
      TaskRecord{12ee53d #270 A=com.example.signatureapp U=0 sz=2}
        Run #1: ActivityRecord{3a99839 u0 com.example.app/.SecondActivity t270}
        Run #0: ActivityRecord{9d6631b u0 com.example.signatureapp/.MainActivity t270}

    mResumedActivity: ActivityRecord{3a99839 u0 com.example.app/.SecondActivity t270}

IntentFilter的匹配规则

   <activity android:name=".SecondActivity">
            <intent-filter>
                <action android:name="com.lxn.test"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:scheme="app"
                    android:host="hello"
                    android:path="/client"
                     android:mimeType="image/*"
                    />
            intent-filter>
        activity>

action匹配规则:必须要和action的字符串相等,区分大小写,如果有多个action,匹配任意一个action就可以
category 匹配规则:启动Activity时,默认会带上

 intent.addCategory(Intent.CATEGORY_DEFAULT);

所以我们要在清单文件中配置category为

<category android:name="android.intent.category.DEFAULT"/>

data对应的格式是
schema://host:port/path|pathPrefix|pathPattern

例如我们要启动上面的Activity,我们的代码应该这么写

 Intent intent = new Intent("com.lxn.test");
     intent.setDataAndType(Uri.parse("app://hello/client"),"image/*");
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        startActivity(intent);

启动Activity之前检查是否有对应的Activity,

 List resolveInfos = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        if (resolveInfos != null && resolveInfos.size() > 0) {
            startActivity(intent);
        }
        //或者
        ResolveInfo resolveInfo = getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
        if (resolveInfo != null) {
            startActivity(intent);
        }

PackageManager.MATCH_DEFAULT_ONLY这个标记的意思是仅仅匹配那些在清单文件中声明了

<category android:name="android.intent.category.DEFAULT"/>

的activity

你可能感兴趣的:(Android开发艺术探索读书笔记(第1章 Activity的生命周期和启动模式))