day02 Activity相关

来源:互联网 发布:网络棋牌违法吗 编辑:程序博客网 时间:2024/06/06 21:53


1.返回栈

Android中的活动是可以层叠的.我们每启动一个新的活动,就会覆盖在原活动之上,然后点击back键的时候
就会销毁最上面的活动,下面的一个活动就会显现出来.

Android是使用任务(Task)来管理活动的,一个任务就是一组放在栈里的活动的集合,这个栈也被称为返回栈(Back Stack).栈是
一种后进先出的数据结构,在默认的情况下,我们每当启动一个新的活动,它会在返回栈中入栈,并处于栈顶的位置.而先前处于
栈顶的Activity就会被压入栈内.而每当我们按下back键或者调用finish()方法销毁一个活动的时候,处于栈顶的活动就会出栈,
这时前一个被压入栈内的活动就会重新处于栈顶的位置.系统总是会显示处于栈顶的活动给用户.

2.活动的状态

每个活动在其生命周期内最多可能出现4种状态:
1> 运动状态(前台状态)
当一个活动处于返回栈的栈顶的时候,这时活动就是处于运行状态的.这时也可以说是活动在前台.
系统最不愿意回收的就是运行状态的activity,因为这样会造成很差的用户体验.

2>暂停状态
当一个活动不再处于栈顶的位置,但仍然部分可见的时候,这时活动就处于暂停状态.处于暂停状态的活动依然
是完全存活着的,系统也不愿意去回收这类活动(因为他是可见的,回收可见的东西对用户会造成很差的用户体验)
只有在内存极低的情况下,系统才会回收这种活动.

3>停止状态
当一个活动不再处于栈顶的位置,并且完全不可见的时候,就进入了停止状态.系统仍然会为这种活动保存相应的状态和成员变量,
但是这并不是完全可靠的,当其他地方需要内存的时候,处于停止状态的活动就有可能被系统回收掉.

4>销毁状态
当一个活动从返回栈中移除以后就变成了销毁的状态.系统会最倾向于回收掉处于这种状态的活动,从而保证手机的内存充足.

3.活动的生命周期

1> onCreate() ->
活动第一次被创建的时候调用,在这个方法中应该完成加载布局,初始化控件设置监听事件等基本操作.
一般启动线程也应该在这个方法中操作.

2>onStart()->
这个方法在活动由不可见变为可见的时候调用.

3>onResume()->
这个方法一般在onStart()方法调用之后调用,它表示活动已经在前台.已经准备好和用户进行交互.此时的活动一定
位于返回栈的栈顶,并处于运行状态.

4>onPause()->
这个方法在系统准备去启动或者恢复另外一个活动的时候调用.我们通常会在这个方法中将一些消耗CPU的资源释放掉,以及保存
一些关键的数据,但是这个方法的执行速度一定要快,不然会影响到新的栈顶活动的使用.

5>onStop()->
这个方法在活动完全不可见的时候调用.它和onPause()方法的主要区别,如果启动的活动是一个对话框,或者是带有透明
主题的activity的时候,那么onPause()方法会得到执行,而onStop()方法不会得到执行.

6>onDestroy()->
这个方法在活动被销毁之前调用,之后活动状态将变为销毁状态.

7>onRestart()->
这个方法在活动由停止状态变为运行状态之前调用,也就是说活动被重新启动了.

以上7个方法,前面6个一般是成对出现的,按照他们执行的区间范围,又可将活动分为三个生存期:
1.完整的生存期
活动在onCreate()方法和onDestroy()方法之间经历的,就是完整的生存期.一般情况下,一个活动会在onCreate()方法中
完成各种初始化操作,而在onDestroy()方法中完成释放内存的操作.

2.可见的生存期
活动在onStart()方法和onStop()方法之间所经历的,就是可见的生存期.在可见生存期内,活动对于用户总是可见的,
即便有可能和用户无法进行交互.我们可以通过这两个方法,合理的管理那些对用户可见的资源.比如在onStart()方法
中对资源进行加载,在在onStop()方法中对资源进行释放,从而保证处于停止状态的活动不会占用太多的内存.

3.前台生存期
活动在onResume()方法和onPause()方法之间经历的,就是前台的生存期.在前台生存期内,活动总是处于运行状态的,
此时的活动是获得用户焦点的,是一定可以用户进行交互的.我们平时接触的最多的活动的转台就是前台生存期.

这里写图片描述

4. 活动被回收了怎么办

1>应用中有一个活动A,在活动A的基础上启动了活动B,活动A就进入了停止状态,这个时候由于系统内存不足,将活动A回收掉了,
然后用户按下Back键盘,返回的时候会出现什么情况.

这个时候还是会显示活动A的,只是这个时候活动A不是执行了onRestart()方法,而是执行了onCreate()方法,因为活动A在这种
情况下相当于被重新创建了一次.
这样一切看起来很正常,但是别忽略了一个情况.这时活动A是由可能实现存有用户输入的数据的,会有一些临时的数据和状态.
如果直接返回的时候,这些数据就会丢失,会给用户带来不好的用户体验.

要想解决这种问题,就要书写onSaveInstanceState()方法,这个方法保证一定会在活动被回收之前调用,因此我们可以通过
这个方法来解决活动被意外回收时,临时数据得不到保存的情况.
onSaveInstanceState(Bundle outState)方法会携带一个Bundle类型的参数,Bundle提供一系列方法用于保存数据,比如可以
使用putString()方法保存字符串,使用putInt()方法保存整型数据,以此类推.每个保存方法必须传入两个参数:
一个是键值,用于以后从Bundle中取出数据.另一个是真正要保存的内容.
String tempData = “something you just typed”;
outState.putString(“data_key”,tempData);

这个时候数据时保存下来了,在哪里进行恢复呢.你会发现onCreate(Bundle savedInstanceState)方法中一直有一个Bundle参数,
这个参数就是我们上面保存的Bundle对象.
if(savedInstanceState != null)
{
String tempData = savedInstanceState.getString(“data_key”); //这里就可以获取之前保存的数据了.
}

5.活动的启动模式

活动的启动模式一共四种:
standard(标准模式,默认模式)
singleTop(单栈顶模式)
singleTask(单栈内模式)
singInstance(单实例模式)

1>standard 启动模式
standard启动模式是默认的启动模式,在没有显示的指定的情况下,所有的活动都会自动使用这样的模式.
对于使用standard模式的活动,每当启动一个新的活动,它不会去查看这个活动是否已经在栈中,是否在栈顶.
而是直接启动一个新的活动,并且让其置于栈顶的位置.

2>singleTop 启动模式
singleTop 模式下的活动,当去启动该模式下的活动的时候,系统回去返回栈的栈顶查看当前处于栈顶的活动是否是要启动的活动,
如果栈顶已经是要启动的活动,则它会直接使用处于栈顶的活动实例,而不去创建一个新的活动的实例.如果没有,则会创建一个新
的activity活动的实例.

3>singleTask 启动模式
singleTask 当去启动该模式下的活动的时候,系统会去整个返回栈中查找是否存在该活动的实例,如果在栈中的某个位置查找到了
该活动已经存在了,则它首先会将该活动之上的所有活动弹出栈,然后让使用该活动实例,并且让其处于栈顶的位置.如果没有,则创建
该活动的新的实例.

4>singleInstance 启动模式
这种模式下的活动,主要是考虑当两个应用程序要共享一个activity的时候,这个时候如果是以上三种方式都无法满足这种需求.
因为每一个android应用程序都在单独的进程当中,都有单独的返回栈.所以这种模式下的活动是开启了一个单独的返回栈来
管理这个活动,不管是哪个应用程序来访问这个活动,都共用的同一个返回栈,也就解决了共享活动实例的问题.

6.活动的最佳实践

6.1 知晓当前是哪一个活动
如果我们想要知道当前显示的Activity是哪一个活动的时候,可以这样做.
1>首先写一个BaseActivity,让其继承自Activity,然后在里面重写onCreate()方法
public class BaseActivity extends Activity
{
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState)
Log.d(“BaseActivity”,getClass().getSimpleName());
}
}
然后让所有的活动都改继承自BaseActivity即可.这样在显示一个Activity的时候,logcat里面就会打印出
当前的activity的类的名字.

6.2 随时随地的退出程序
如果我们启动的活动过多,而活动又是可以一层一层的堆叠上去的.这样我们如果要退出当前的应用程序的时候,
就需要按很多次的back键盘,如何做到一个按钮就可以随时随地的退出整个应用程序,销毁所有的活动呢?

我们首先写一个ActivityCollector工具类,里面有一个集合,存放我们的活动.有一个往集合里增加活动的方法,
有一个往集合里面删除活动的方法,还有一个方法是删除所有的集合.
我们在每个活动创建的时候都调用它的增加活动的方法,在每个活动销毁的时候都调用它的删除活动的方法.
而在我们要退出的地方调用它的删除所有活动的方法即可.
ActivityCollector.Java

package com.fioman.my02_activity;import java.util.ArrayList;import java.util.List;import android.app.Activity;/** * 活动管理器,用于添加删除活动,或者一次性删除所有的活动 * @author FioMan * */public class ActivityCollector{    /**     * 所有的已经创建并且没有被销毁的活动,也即是所有的存货的活动     */    public static List<Activity> activities = new ArrayList<Activity>();
<span class="hljs-javadoc">/** * 向活动的集合中添加一个活动 *<span class="hljs-javadoctag"> @param</span> activity  要添加的活动 */</span><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">addActivity</span>(Activity activity){    activities.add(activity);}<span class="hljs-javadoc">/** * 向活动中移除一个活动 *<span class="hljs-javadoctag"> @param</span> activity 要移除的活动 */</span><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">removeActivity</span>(Activity activity){    activities.remove(activity);}<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">finishAll</span>(){    <span class="hljs-keyword">for</span>(Activity activity : activities)    {        <span class="hljs-keyword">if</span>(!activity.isFinishing())        {            activity.finish();        }    }}

}

然后写一个BaseActivity ,让所有的活动该继承自BaseActivity即可
BaseActivity.java

package com.fioman.my02_activity;import android.app.Activity;import android.os.Bundle;public class BaseActivity extends  Activity{    @Override    protected void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        /**         * 活动创建的时候添加到管理活动的集合中         */        ActivityCollector.addActivity(this);    }
<span class="hljs-annotation">@Override</span><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onDestroy</span>(){    <span class="hljs-keyword">super</span>.onDestroy();    ActivityCollector.removeActivity(<span class="hljs-keyword">this</span>);}

}

0 0