乐趣区

关于android:字节Android工程师都在学习的Activity与Activity调用栈你都学习了

本文为 Android 的 Activity 相干常识整顿,具体参考了

《Android 开发艺术摸索》第一章
《Android 群英传》第八章
《第一行代码》第二章
Activity 是与用户交互的第一接口。

Activity 生命周期
Activity 具备多种状态。其生命周期图如下:

其中,有三个稳固态,其余都是过渡态:

Resumed,此时,Activity 处于栈顶,解决用户交互。
Paused,当 Activity 的一部分被挡住的时候进入这个状态,不会与用户交互。
Stopped,当 Activity 齐全被笼罩时进入这个状态,此时 Activity 不可见,仅在后盾运行。

1.1 Activity 经典生命周期

(以下均指 MainActivity 的生命周期)

Activity 启动,点开一个利用展现 MainActivity
onCreate()->onStart()->onResume() 达到 Resumed 状态,此时 MainActivity 被关上。

Activity 暂停与复原,1: 关上了一个半屏幕的 dialog,2: 按返回键返回 MainActivity
onPause()达到 Paused 状态,此时 dialog 被关上。
onResume()达到 Resumed 状态,此时 dialog 被敞开,显示 MainActivity

Activity 进行与复原,1: 关上另一个 SecondActivity,2: 按返回键返回 MainActivity
onPause()->onStop()到 Stopped 状态,此时 SecondActivity 被关上。
onRestart()->onStart()->onResume()到 Resumed 状态,此时 SecondActivity 被敞开,从新回到 MainActivity。

Activity 销毁,在 MainActivity 按返回键
onPause()->onStop()->onDestory(),此时曾经销毁 MainActivity。
留神:
在 onPause()中肯定要开释应用的系统资源,比方 Camera,sensor,receivers!!
在 onStop()中执行更大、更多 CPU 密集的敞开操作。比方写入信息到数据库。
当零碎长期处于 onStopped 状态而且此时零碎内存缓和时,零碎会回收此 Activity,而此时,零碎会通过 onSaveInstanceState()办法将 Activity 状态保留到 Bundle 对象中(finish()办法销毁时不会保留)。当从新创立此 Activity 时,保留的 Bundle 对象会传递到 onRestoreInstanceState()与 onCreate()中。
onCreate 和 onDestroy 是配对的,别离标识着 Activity 的创立和销毁; onStart 和 onStop 是配对的,标识着 Activity 是否可见;onResume 和 onPause 是配对的,标识着 Activity 是否在前台。
假如以后 Activity 为 MainAcitivty,这时用户启动 SecondActivity,那么 MainAcitivty 的 onPause 先执行,SecondActivity 的 onResume 后执行。Android 规定,不能在 onPause 中做重量级操作,就是基于这里。咱们应该尽量在 onStop 中做操作,使得新 Activity 尽快显示
MainAcitivty->onPause
SecondActivity->onCreate
SecondActivity->onStart
SecondActivity->onResume
MainAcitivty->onStop

1.2 异样生命周期

以下几种状况下,Activity 的生命周期会产生异样
1,资源相干的系统配置产生扭转
比方,旋转屏幕,在默认状态下,Activity 就会被销毁并且从新创立。

首先,Activity 就会被销毁,onPause(), onStop(),onDestory()均会被调用,同时因为 Activity 是在异样状态下终止的,零碎会在 onStop()之前,调用 onSaveInstanceState()来保留以后 Activity 的状态。
而后,Activity 被从新创立,零碎会在 onStart()之后,调用 onRestoreInstanceState(),并且把之前保留的 Bundle 对象传递给 onRestoreInstanceState()和 onCreate()办法。
PS: 这两个办法都能对 Bundle 数据进行解决,然而个别用 onRestoreInstanceState()。因为 onRestoreInstanceState()一旦被调用,其参数 Bundle savedInstanceState 肯定是有值的,咱们不用判断其是否为空。

@Override protected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if(savedInstanceState != null){String test = savedInstanceState.getString("extre_test"); Log.d(TAG, test); } } @Override protected void onSaveInstanceState(Bundle outState){super.onSaveInstanceState(outState);   outState.putString("extre_test", "test"); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState){super.onRestoreInstanceState(savedInstanceState); String test = savedInstanceState.getString("extre_test"); Log.d(TAG, test); } 

执行程序:
1 onPause()
2 onSaveInstanceState(Bundle outState)
3 onStop()
4 onDestory()
5 onCreate(Bundle savedInstanceState)
6 onStart()
7 onRestoreInstanceState(Bundle savedInstanceState)

留神:零碎仅仅在 Activity 异样终止时才会调用 onRestoreInstanceState()。

2,零碎内存不足
此时的零碎中数据的存储和复原状况和下面第一种状况统一。Activity 优先级如下:

1 前台 Activity
2 可见但非前台 Activity
3 后盾 Activity
当系统资源有余的时候,会依照这个优先级应用 onSaveInstanceState()和 onRestoreInstanceState()来存储和复原数据。

还有一些后盾过程不是四大组件,这样就会很容易被杀死~~ 个别是将这些后盾工作放入 Service 中,从而保障有肯定的优先级。

PS:阻止 Activity 被从新创立

应用 android:configChanges=”orientation|screenSize” 属性。

罕用属性:

locale:设施的本地地位发生变化,个别指切换了零碎语言。
orientation:屏幕方向发生变化
screenSize:屏幕大小发生变化,当旋转屏幕的时候,屏幕尺寸会变!!!!这个比拟非凡,当 minSdkVersion 和 targetSdkVersion 均低于 13 时,此选项不会导致 Activity 重启,否则会导致 Activity 重启。
keyboardHidden:键盘的可拜访性发生变化,比方调出键盘。

<activity android:name=".MainActivity" android:label="@string/app_name" android:configChanges="orientation|screenSize|keyboardHidden" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>  @Override public void onConfigurationChanged(Configuration newConfig){super.onConfigurationChanged(newConfig);     ......// 当系统配置发上变换时,进行的工作 }  

Android 工作栈
Android 的 APP 通常会有多个 Activity,各个 Activity 之间通过 Intent 进行连贯,零碎通过栈构造来保留整个 APP 的 Activity。零碎有两种形式管制 Activity 的启动模式。

AndroidMainifest 的 launchMode
Intent Flag(优先级更高)

2.1AndroidMainifest 启动模式

在 AndroidMainifest.xml 文件外面的 activity 标签设置启动模式。

<activity android:name=".FirstActivity" android:launchMode="singleTop" android:label="This is FirstActivity" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> 

standard,规范模式,每次都会创立新的 Activity 笼罩在原 Activity 上

singleTop,栈顶复用模式,首先判断栈顶 Activity 是否是要启动的 Activity,如果是则不创立新的 Activity 而间接援用这个 Activity;如果不是则创立新的 Activity。

singleTask,栈内复用模式,检测整个 Activity 栈中是否存在以后须要启动的 Activity,如果存在则将该 Activity 置于栈顶,并销毁其上所有 Activity。

singleInstance,单实例模式,创立新的工作栈,且该工作栈仅有一个 Activity。

TaskAffinity
taskAffinity,工作相关性。xml 中的一个属性,标识了一个 Activity 所须要的工作栈的名字。默认是包名。如果设置了其余的名字如 com.test.task1,那启动它的时候就会新建一个名为 com.test.task1 的工作栈。

<activity android:name="com.test.task0.MainActivity" android:label="@string/app_name" android:launchMode="standard"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category andorid:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity andorid:name="com.test.SecondActivity" android:taskAffinity="com.test.task1" android:label="@string/app_name" android:launchMode="singleTask"/> <activity andorid:name="com.test.ThirdActivity" android:taskAffinity="com.test.task1" android:label="@string/app_name" android:launchMode="singleTask"/> 

如果从 MainActivity 启动 SecondActivity,而后再启动 ThirdActivity,那么工作栈如下:
com.test.task0 MainActivity
com.test.task1 SecondActivity ThirdActivity
若再从 ThirdActivity 启动 MainActivity,那么工作栈如下:
com.test.task0 MainActivity
com.test.task1 SecondActivity ThirdActivity MainActivity

2.2 Intent Flag 启动模式

对 Intent 进行设置

Intent intent = new Intent();  intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

重要的 Flag:

FLAG_ACTIVITY_NEW_TASK,启动的 Activity 在新的 Task 中,相当于 android:launchMode=”newTask”
FLAG_ACTIVITY_SINGLE_TOP,相当于 android:launchMode=”singleTop”
FLAG_ACTIVITY_CLEAR_TOP,相当于 android:launchMode=”singleTask”
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS,当以此种模式启动 A,A 再启动 B 时,A 会被销毁。等同于 android:excludeFromeRecents=”true”
3 IntentFilter 的匹配规定

<activity android:name="SecondActivity"> <intent-filter> <action android:name="android.intent.action.SEND"> <category android:name="android.intent.category.DEFAULT"> <data android:mimeType="text/plain"> </intent-filter> </activity> 

调用一个 Activity 次要包含两种:
1,显式调用。

Intent intent = new Intent(MainActivity.this,SecondActivity.class); startActivity(intent); 

2, 隐式调用

Intent intent = new Intent(Intent.ACTION_SEND); intent.setDataAndType(Uri.parse("file://abc"), "text/plain"); startActivity(intent); 

隐式调用须要 Intent 可能匹配指标组件的 IntentFilter 中的过滤信息。
IntentFilter 中的过滤信息有 action, category, data。
只有一个 Intent 同时匹配这三个类别能力启动指标 Activity。

action 的匹配要求,Intent 中的 action 存在且必须和过滤规定中的其中一个 action 雷同。
data 的匹配要求,Intent 中的 data 存在且必须和过滤规定中的其中一个 data 雷同。
category 匹配要求,如果含有 category,那么所有的 category 都必须和过滤规定中的其中一个 category 雷同。也就是说它的 category 能够没有!!!!!(起因是默认的 category 是 android.intent.category.DEFAULT,不过得在 activity 标签的 intent-filter 中退出 android.intent.category.DEFAULT 这个 category)
退出程序的两种办法

4.1 利用 Activity 的 singleTask 模式退出

将主 Activity 设置为 singleTask 模式

<activity      android:name=".MainActivity"      android:launchMode="singleTask"      ...  

在要退出的 Activity 直达到主 Activity 中,从而将主 Activity 之上的 Activity 都革除

Intent intent = new Intent(this, MainActivity.class); startActivity(intent); 

而后重写主 Activity 的 onNewIntent()办法,在办法中加上 finish(),从而销毁最初一个 Activity。

@Override protected void onNewIntent(Intent intent) {super.onNewIntent(intent); finish();} 

4.2 利用专门的汇合类对所有的流动进行治理
创立一个 ActivityCollector 类作为流动管理器。List<Activity> 作为寄存流动的列表。

public class ActivityCollector {public static List<Activity> activities = new ArrayList<Activity>(); public static void addActivity(Activity activity) {activities.add(activity); } public static void removeActivity(Activity activity) {activities.remove(activity); } public static void finishAll() { for (Activity activity : activities) {if (!activity.isFinishing()) {activity.finish(); } } } } 

创立一个继承自 Activity 的 BaseActivity。ActivityCollector 里寄存的流动要随着 onCreate 而增加,随着 onDestory 而销毁。

public class BaseActivity extends Activity {@Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); Log.d("BaseActivity", getClass().getSimpleName()); ActivityCollector.addActivity(this); } @Override protected void onDestroy() { super.onDestroy(); ActivityCollector.removeActivity(this); } } 

全副的 Activity 都要继承自 BaseActivity,此时,只有调用 ActivityCollector.finishAll();,就能够销毁所有 Activity,关掉程序。
欢送各位技术大佬一起交换探讨,记得点击下上方的关注哦,这样就能够及时看到音讯啦!

退出移动版