Activity

作者: jacky123 | 来源:发表于2016-06-15 17:29 被阅读62次

    1.生命周期

    第一次启动:
    onCreate->onStart->onResume
    跳转其他页面:
    onPause->onStop
    回到页面:
    onRestart->onStart->onResume
    结束当前页面:
    onPause->onStop->onDestroy

    异常情况下的生命周期分析

    onSaveInstanceState 与 onRestoreInstanceState(TextView 等都有这个方法)
    对于 onSaveInstanceState 的调用说明:

    Android calls onSaveInstanceState() before the activity becomes vulnerable to being destroyed by the system, but does not bother calling it when the instance is actually being destroyed by a user action (such as pressing the BACK key)
    从这句话可以知道,当某个activity变得“容易”被系统销毁时,该activity的onSaveInstanceState就会被执行(按 home 旋转屏幕等等),除非该activity是被用户主动销毁的,例如当用户按BACK键的时候。

    对于onRestoreInstanceState什么时候被调用

    onRestoreInstanceState()被调用的前提是,activity A“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用,例如,当正在显示activity A的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到activity A,这种情况下activity A一般不会因为内存的原因被系统销毁,故activity A的onRestoreInstanceState方法不会被执行 此也说明上二者,大多数情况下不成对被使用。

    • 我们可以通过 onRestoreInstanceState 和 onCreate 方法来判断Activity是否被重建了,
    • 可以通过android:configChanges="orientation|screenSize"...来阻止Activity重新创建。

    问题1:
    当前页面是 Activity A ,如果用户打开一个新的 Activity B, 那么 B 的 onResume 和 A 的 onPause 那个先执行?

    A->onPause
    B->onCreate
    B->onStart
    B->onResume
    A->onSaveInstanceState
    A->onStop


    2.任务栈

    Task是为了完成某个工作的一组相关联的Activity的集合
    为了方便大家更直观感受一下,可以使用adb命令查看一下当前运行的Task:

    adb shell dumpsys activity activities

    注意其中的几个关键字

    Stack
    TaskRecord
    ActivityRecord

    用图形来表示他们之间的关系


    "Hist"代表Task中的ActivityRecord,可以理解成对应某个实际的Activity。
    "Stack #0"表示mHomeStack(ActivityStack类),保存了Launcher相关的Activity的Task。
    "Stack #1"表示mFocusStack(ActivityStack类),用于保存Launcher除外的其他应用的Activity组成的Task。

    这两个Stack由ActivityStackSupervisor负责组织管理,在Android 4.4之前的版本是没有ActivityStackSupervisor这个类的,也没有"Stack #"的划分,AMS直接管理Task的列表。

    TaskRecord{4226f148 #60 A=com.ryg.chapter_1 U=0 sz=5}       
    Run #5: ActivityRecord{41a7e988 u0 com.ryg.chapter_1/.MainActivity t60}
    Run #4: ActivityRecord{41a68f40 u0 com.ryg.chapter_1/.MainActivity t60}
    Run #3: ActivityRecord{418d32f8 u0 com.ryg.chapter_1/.MainActivity t60}
    Run #2: ActivityRecord{4212a450 u0 com.ryg.chapter_1/.MainActivity t60}
    Run #1: ActivityRecord{4226ee78 u0 com.ryg.chapter_1/.MainActivity t60}
    

    其中 com.ryg.chapter_1 代表 taskAffinity 值,我们也可以为一个Activity指定任务栈,如下:
    TaskAffinity 标识了一个 Activity 所需要的任务栈。默认情况下,所有 Activity 所需的任务栈的名字为当前应用的包名。

    <activity
        android:name="com.ryg.chapter_1.MainActivity"
        android:configChanges="orientation|screenSize"
        android:launchMode="singleTask"
        android:taskAffinity = "com.jack.org1"></activity>
    

    3.启动模式

    • standard:
      标准启动,Activity每次都会 onCreate
    • singleTop:
      如果置于栈顶 onNewIntent(),如果栈中不存在这个Activity,onCreate会调用。反之则 onNewIntent();
    • singleTask:
      检测整个 Activity 栈是否有当前需要启动的 Activity,自带 clear 属性。特殊情况:其他程序以 singleTask 启动创建一个新的任务栈。 如果栈中不存在这个Activity,onCreate会调用。反之则 onNewIntent();
    • singleInstance:
      单实例模式,除了拥有singleTask的属性外,还加强了一点,就是这种模式的Activity只能单独位于一个任务栈中。

    指定启动模式

    • <manifest> 中指定。
    • Intent 中为 Activity 设置标记位,优先级高些。
    Intent intent = new Intent();
    intent.setClass(MainActivity.this,SecondActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
    

    Flags 常见的标记位

    1.FLAG_ACTIVITY_NEW_TASK
    当Intent对象包含FLAG_ACTIVITY_NEW_TASK标记时,系统在查代时(和设置了singleTask启动模式一样都是)按Activity的taskAffinity属性进行匹配,如果找到一个Task的taskAffinity与之相同,就将目标Activity压入此Task栈中,如果找不到则创建一个新的Task。
    2.FLAG_ACTIVITY_SINGLE_TOP
    3.FLAG_ACTIVITY_CLEAR_TOP
    4.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
    不希望用户通过历史列表回到我们的 Activity 的时候,这个标记位比较有用。

    4.startActivityForResult

    注意点:要保证 要启动的 activity 的启动模式是 standard, A 启动 B.
    一般这样封装比较好,如下:

    1. 在 B 中,设置一个方法,供 A 去启动 B
    public static void startChoosePayActivity(Activity activity, int guaranteeFee, int requestCose) {
        Intent intent = new Intent(activity, ChoosePayActivity.class);
        intent.putExtra("guaranteeFee", guaranteeFee);
        if (requestCose == -1) {
            activity.startActivity(intent);
        } else {
            activity.startActivityForResult(intent, requestCose);
        }
    }
    
    1. 在 B 中传递数据给 A。
    setResult(RESULT_OK, getIntent().putExtra("paytype", result));
    finish();
    
    1. 在 A 的 onActivityResult 取出值
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode != RESULT_OK) {
            return;
        }
    
        switch (requestCode) {
            case IntentContent.PAYTYPE_SELECT_REQUEST:
                int nPaytype = data.getIntExtra("paytype", -1);
                E_PAY_TYPE e_pay_type = E_PAY_TYPE.valueOf(nPaytype);
                switch (e_pay_type) {
                    case PAY_ALIPAY:
                        LogUtils.i(TAG, "支付宝支付");
                        break;
                    case PAY_WECHAT:
                        LogUtils.i(TAG, "微信支付");
                        break;
                    case PAY_WALLET:
                        LogUtils.i(TAG, "钱包支付");
                }
                break;
        }
    }
    

    参考资料

    相关链接

    相关文章

      网友评论

          本文标题:Activity

          本文链接:https://www.haomeiwen.com/subject/yglpdttx.html