第一行代码-活动的生存周期
来源:互联网 发布:复制淘宝店铺违规吗 编辑:程序博客网 时间:2024/05/23 01:14
1.返回栈
Android是使用任务(Task)来管理活动的,一个任务就是一组存放在栈里的活动的集合,这个栈被称作返回栈(back Stack)。栈是一种先进先出的数据结构。
每当启动了一个新的活动,会在返回栈中入栈,并处于栈顶的位置,使用Back键或调用finish()方法销毁一个活动时,处于栈顶的活动会出栈,这时前一个入栈
的活动就会处于栈顶的位置。系统会显示处于栈顶位置的活动给用户。
2.活动状态
每个活动在其生命周期最多会有四种状态。
1.运行状态
活动位于返回栈的栈顶位置,活动就能够处于运行状态。系统最不愿意回收的就是处于运行状态的活动。
2.暂停状态
活动不处于栈顶位置,仍然可见,活动就进入了暂停状态。并不是每一个活动都会占满整个屏幕。
3.停止状态
活动部处于栈顶位置,并且完全不可见的时候,就进入了停止状态。
4.销毁状态
活动从返回栈中移除后,就变成了销毁状态,系统倾向于回收处于这种状态的活动,从而保证手机的内存充足。
3.活动的生存期
Activity类定义了7个回调方法,覆盖了活动生命周期的每个环节。
*onCreate()。活动第一次创建的时候调用。在这个方法中完成活动的初始化操作。比如加载布局、绑定事件等。
*onStart()。活动由不可见变为可见时调用。
*onResume().在活动准备好和用户进行交互的时候调用。此时的活动位于返回栈的栈顶,并且处于运行状态。
*onPause().系统准备去启动或者恢复另一个活动的时候调用。在这个方法中将一些消耗CPU的资源释放掉,以及保存一
些关键数据,这个方法的执行速度要快,不然会影响栈顶活动的使用。
*onStop()。活动完全不可见的时候调用。它和onPause的区别是,如果启动的新活动是一个对话框式的活动,那么onPause()方法
会得到执行。而onStop()方法并不会执行。
*onDestroy().在活动销毁前调用,之后活动的状态变为销毁状态。
*onRestart()。活动由停止状态变为运行状态之前调用,也就是活动被重新启动了。
活动可以分为3种生存周期。
*完整生存期。 活动在onCreate()方法和onDestroy()方法之间经历的就是完整生存周期。活动在onCreate()方法中完成各种初始化操作。
而onDestroy()方法中完成释放内存的操作。
*可见生存期。活动在onStart()方法和onStop()方法之间经历的就是可见生存期。在可见生存期内,活动是可见的,在onStart()方法中对
资源进行加载,在onStop()方法内对资源进行释放。从而保证处于停止状态的活动不会占用过多内存。
*前台生存期。活动在onResume()方法和onPause方法之间所经历的就是前台生存期.在前台生存期内,活动是处于运行状态的。此时的活动
可以和用户进行交互。
当Main活动第一次被创建时会依次执行onCreate()、onStart()和onResume()方法。Main活动通过intent启动second活动,将Main活动完全遮挡住,onPause()
和onStop()方法都会得到执行。按下back键返回Main活动时,onRestart()方法会得到执行,然后依次执行onStart()和onResume()方法。注意此时的onCreate()方法
不会执行,因为Main活动没有得到创建。这时启动一个对话框,Main活动没有被完全遮挡,只有onPause()方法得到了执行,onStop()方法没有执行。最后按下back键
退出程序,onPause()、onStop()和onDestroy()方法会依次得到执行。最终销毁Main活动。
4.活动被回收
如果活动进入了停止状态,有可能被系统回收。那么活动中是可能存在临时数据区和状态的就可能会丢失。Activity中提供了一个onSaveInstance()回调方法。这个
回调方法会保证活动被回收之前调用。通过这个方法可以解决活动被回收时临时数据得不到保存的问题。
onSaveInstance()方法带一个Bundle类型的参数,Bundle提供了方法用于保存数据,比如putString()方法保存字符串、使用putInt()方法保存整型数据,以此类推。
每个保存方法需要传入两个参数,第一个参数是键,用于后面从Bundle中取值,第二个参数是保存的内容。
@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); String tempData = "sommthinng you just typed"; outState.putString("data_key",tempData); }
字符串数据tempData已经保存了,如果活动在被系统回收前通过onSaveInstanceState()方法来保存数据,onCreate()方法中的参数Bundle就会带有之前保存
的全部数据,只需要通过相应的取值方法将数据取出。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if(savedInstanceState != null) { String tempData = savedInstanceState.getString("data_key"); } }将保存的数据取出后在重新恢复给活动就可以了。Bundle保存数据和取出数据的方法和Intent传递数据使用的是类似的方法。
Intent方法还可以结合Bundle一起用于传递数据。首先可以把数据保存在Bundle对象中,然后再将Bundle对象存放在Intent中。到了目标活动再从Intent中
取出Bundle对象,再从Bundle中一一取出数据。
5.活动的启动模式
活动有四种启动模式,分别是standard、singleTop、singleTask和singleInstance。可以在AndroidManifest.xml中通过<activity>标签
指定android:launchMode属性来选择启动模式.
5.1 standard
standard是活动默认的启动模式,在不进行显示指定的情况下,所有的活动都会自动使用这种模式。Android使用返回栈来管理活动的,每当启动一个新的活动,它就会在返回栈中入栈,并处于栈顶的位置,使用standard模式的活动,系统不论活动是否在返回栈中存在,每次启动都会创建一个新的实例。
5.2 singleTop
当活动的启动模式是singleTop,那么启动活动的时候如果发现返回栈的栈顶已经是该活动,则认为可以直接使用它,不会再创建新的 活动实例。
在AndroidManifest.xml标签内修改MainActivity的启动模式为singleTop。
<activity android:name=".MainActivity" android:lunchMode="singleTop"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>当MainActivity处于返回栈栈顶位置时,每一次启动MainActivity时都会直接使用栈顶的活动,因此MainActivity只会有一个实例。只按一次Back键就可以退出程序。
当MainActivity并未处于栈顶位置时,再启动MainActivity还是会创建新的实例的。
singleTop模式的示意原理图如下:
5.3 singleTask
当活动指定为singleTask,每次启动活动都会检查返回栈中是否存在该活动的实例,如果存在则直接使用该实例,并把这个活动之上的所有活动全部出栈,
如果没有则创建一个新的活动实例。
指定活动的启动模式为singleTask。
<activity android:lunchMode="singleTask" android:name=".MainActivity" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
在SecondActivity中启动FirstActivity时,会发现返回栈中已经存在了一个FirstActivity的实例,并且在SecondActivity的下面,于是SecondActivity会从返回栈中出栈,而FirstActivity
重新成为了栈顶活动。因此FirstActivity的onRestart()方法和SecondActivity的onDestroy()方法会得到执行。
singleTask的示意图如下:
5.4 singleInstance
指定为singleInstance模式的活动会启用一个新的返回栈来管理这个活动。如果程序中有一个活动可以允许其他程序调用,使用能够前面的三种启动模式无法
实现。因为每个应用程序都有自己的返回栈,同一个活动在不同的返回栈中入栈时必然是创建了新的实例。而使用singleInstance模式可以有一个单独的返回栈来管理活动。
这样不论哪个应用程序来访问这个活动都共用一个返回栈,也就实现了共享活动。
在AndroidManifest.xml中修改启动模式为singleInstance
<activity android:lunchMode="singleInstance" android:name=".MainActivity" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>使SecondActivity的启动模式为singleInstance.singleInstance模式的原理示意图如下:
6.活动的实践
6.1知晓当前是哪一个活动
public class BaseActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d("BaseActivity", getClass().getSimpleName()); }}在onCreate()方法中获取了当前实例的类名,并通过Log打印了出来。
6.2 随时随地退出程序
如果程序中启动了太多活动,在返回栈中有太多活动入栈,在当前的活动(栈顶的活动)退出程序是非常不方便的 。需要连续按Backed键退出,将活动从返回栈
中出栈。按HOME键只是把程序挂起。可以通过一个专门的集合类来对所有的活动进行管理,进而实现一个注销或者退出的功能。
新建一个ActivityCollector类作为活动管理器。
public class ActivityCollector { public static ArrayList<Activity> sActivityListies = new ArrayList<>(); public static void addActivity(Activity activity) { sActivityListies.add(activity); } public static void removeActivity(Activity activity) { sActivityListies.remove(activity); } public static void finishAll() { for(Activity activity:sActivityListies) { if (!activity.isFinishing()) { activity.finish(); } } }}
在活动管理器中通过一个List来管理活动,然后提供了一个addActivity()方法用于向List中添加活动,提供了一个removeActivity()方法用于从List中移除活动,最后提供了一个finishAll()方法用于将List中存储的活动全部销毁。
接下来修改BaseAcitivity中的代码。如下所示:
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.onCreate(savedInstanceState); Log.d("BaseActivity", getClass().getSimpleName()); ActivityCollector.addActivity(this); } @Override protected void onDestroy() { super.onDestroy(); ActivityCollector.removeActivity(this); }
在BaseAcitivity的onCreate()方法中调用了ActivityCollector的addActivity()方法表明当前正在创建的活动添加到活动管理器。然后在BaseActivity中重写
onDestroy()方法,并且调用了AcitivityCollector的removeActivity()方法,表明将马上一个马上要销毁的活动从活动管理器中移除。
从此想要退出程序只需要调用ActivityCollector.finishAll()方法就可以了。
可以在销毁活动的代码后面加上杀掉当前进程的代码,保证程序完全退出。杀掉进程的代码如下:
android.os.Process.killProcess(android.os.Process.myPid);killProcess()方法用于杀掉一个进程,他接收一个进程的id参数,可以通过myPid()方法来获取当前程序的进程id。需要注意的是killProcess()方法只能
用于杀掉当前程序的进程,不能使用这个方法杀掉其他程序。
6.3启动活动的最佳写法
通过在SecondActivity活动中添加actionStart()方法,在这个方法中完成了Intent的构建,另外所有SecondActivity中需要的数据都通过actionStart()方法的参数
传递过来。然后存储到Intent中,最后通过startActivity()方法启动
public static void actionStart(Context context, String data1, String data2) { Intent intent = new Intent(context, SecondActivity.class); intent.putExtra("param1", data1); intent.putExtra("param2",data2); context.startActivity(intent); }
- 第一行代码-活动的生存周期
- 活动的生存周期
- 活动的生存周期
- android活动的生存周期
- 活动的最佳实践--第一行代码
- 安卓活动的生存周期
- 活动和服务之间的通信 第一行代码
- 第一行代码2.5-活动的启动模式
- 第一行代码2.6-活动的最佳实践
- 浅谈活动的生命周期(读《第一行代码》有感)
- 《第一行代码》自学笔记-活动的基本用法
- 活动的四种启动模式(第一行代码总结)
- Android 基础 —— 活动的生存周期
- Android 基础 —— 活动的生存周期
- 《第一行代码》读书笔记(一)----活动
- 《第一行代码》启动活动最佳写法
- Android--第一行代码笔记 活动生命周期
- 活动(Activity)---《第一行代码Android》笔记
- markdown编辑器
- 初学Qt:内存回收机制
- 欢迎使用CSDN-markdown编辑器
- ccf刷题记04
- 剑指offer:二叉树的镜像
- 第一行代码-活动的生存周期
- 51 nod 1623 完美消除(单调栈+数位DP)
- Linux入门(一)
- 虚方法virtual和抽象方法abstract以及多态的研究(重新整理)
- 手动绕过百度加固Debug.isDebuggerConnected反调试的方法
- JAVA连接MySQL数据库(可转换成SQL Server、Oracle连接方式)(精华版)
- 26.nginx 跨域
- 涉及2张表的员工涨工资问题
- Java 并发 —— volatile 关键字