根 Activity 变化
1、问题引入
- 从 SplashAvtivity 跳转到了 LoginAvtivity,这种写法,是不是可以让 LoginAvtivity 成为根 Activity?
startActivity(newIntent(SplashAvtivity.this,LoginActivity.class));finish();2、演示
(1)Activity
- StartActivity
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".StartActivity"><Buttonandroid:id="@+id/btn_go"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="前进"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"/></androidx.constraintlayout.widget.ConstraintLayout>publicclassStartActivityextendsAppCompatActivity{publicstaticfinalStringTAG=StartActivity.class.getSimpleName();@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_start);test();}privatevoidtest(){Log.i(TAG,"taskId: "+getTaskId());Log.i(TAG,"intent: "+getIntent().toString());Log.i(TAG,"isTaskRoot: "+isTaskRoot());ButtonbtnGo=findViewById(R.id.btn_go);btnGo.setOnClickListener(v->{Intentintent=newIntent(this,FinishActivity.class);startActivity(intent);});}}- FinishActivity
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".FinishActivity"><Buttonandroid:id="@+id/btn_back"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="前进"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"/></androidx.constraintlayout.widget.ConstraintLayout>publicclassFinishActivityextendsAppCompatActivity{publicstaticfinalStringTAG=FinishActivity.class.getSimpleName();@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_finish);test();}privatevoidtest(){Log.i(TAG,"taskId: "+getTaskId());Log.i(TAG,"intent: "+getIntent().toString());Log.i(TAG,"isTaskRoot: "+isTaskRoot());ButtonbtnBack=findViewById(R.id.btn_back);btnBack.setOnClickListener(v->finish());}}(2)Test
- 应用启动,打开 StartActivity,输出结果如下
StartActivity - taskId: 170 StartActivity - intent: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.my.activity/.StartActivity } StartActivity - isTaskRoot: true- 点击【前进】按钮,跳转到 FinishActivity,输出结果如下
FinishActivity - taskId: 170 FinishActivity - intent: Intent { cmp=com.my.activity/.FinishActivity } FinishActivity - isTaskRoot: false(3)Change Test
- 在 StartActivity 中,进行如下修改
Log.i(TAG,"taskId: "+getTaskId());Log.i(TAG,"intent: "+getIntent().toString());Log.i(TAG,"isTaskRoot: "+isTaskRoot());ButtonbtnGo=findViewById(R.id.btn_go);btnGo.setOnClickListener(v->{Intentintent=newIntent(this,FinishActivity.class);startActivity(intent);finish();});- 应用启动,打开 StartActivity,输出结果如下
StartActivity - taskId: 171 StartActivity - intent: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.my.activity/.StartActivity } StartActivity - isTaskRoot: true- 点击【前进】按钮,跳转到 FinishActivity,输出结果如下
FinishActivity - taskId: 171 FinishActivity - intent: Intent { cmp=com.my.activity/.FinishActivity } FinishActivity - isTaskRoot: true3、小结
原 Activity 是根 Activity,启动新 Activity 后立即调用 finish 方法
新启动的 Activity 会继承原任务栈,新 Activity 会成为新的根 Activity
4、优化策略
- 清空栈顶并设为根,在 Intent 中添加
FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK标志
Intentintent=newIntent(SplashActivity.this,LoginActivity.class);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK);startActivity(intent);FLAG_ACTIVITY_CLEAR_TASK:清除原任务栈中所有 ActivityFLAG_ACTIVITY_NEW_TASK:在新任务中启动,此时的 Activity 就是新栈的根
5、补充学习
getTaskId 方法用于返回当前 Activity 所在任务栈的唯一 ID
getIntent 方法用于返回启动当前 Activity 的 Intent 对象,这个 Intent 对象包含了启动该 Activity 时的所有信息,有 Action、Data、Category、Flags、Extras 等
isTaskRoot 方法用于判断当前 Activity 是否是其所在任务栈的根 Activity,即栈底第一个 Activity
APP 崩溃与自动重启
- 在 Application 中,有如下处理
Thread.setDefaultUncaughtExceptionHandler((t,e)->{Log.i(TAG,"defaultUncaughtExceptionHandler: "+e.getMessage());...System.exit(1);});从 LoginActivity 跳转到了 MainActivity,从 MainActivity 跳转到了 ComputeActivity
在 ComputeActivity 中操作时,报错了,现象如下
白屏了几秒后,回到了 LoginActivityLog.i(TAG, "defaultUncaughtExceptionHandler: " + e.getMessage()) 有 7 次打印 第 1 次打印是 ComputeActivity 的报错触发 后面的 6 次打印是 MainActivity 的报错触发,因为 MainActivity 不支持直接启动,需要从 LoginActivity 跳转 MainActivity也就是说,ComputeActivity 报错,APP 自动重启,打开 MainActivity 但是,MainActivity 报错,APP 自动重启,打开 MainActivity,这样重复了多次 最后,MainActivity 报错,APP 自动重启,打开 LoginActivity- 如果不调用 setDefaultUncaughtExceptionHandler 方法,同样的情况,现象如下
白屏了几秒后,回到了 LoginActivityComputeActivity 报错,APP 自动重启,打开 MainActivity MainActivity 报错,APP 自动重启,打开 LoginActivity- 修改了 setDefaultUncaughtExceptionHandler 方法,同样的情况,现象如下
Thread.setDefaultUncaughtExceptionHandler((t,e)->{Log.i(TAG,"defaultUncaughtExceptionHandler: "+e.getMessage());...Intentintent=newIntent(this,LoginActivity.class);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK);startActivity(intent);System.exit(1);});白屏后回到了 LoginActivityComputeActivity 报错,APP 自动重启,打开 LoginActivity