一、基础
看了官方文档之后,自己领悟过来接着翻译的,由于第一次的原因,技术水品乜有跟上,还请大家将就将就。如果你有更好的建议的,希望你可以提出,如果你觉得哪里写的不好的,恳请留下你的指导意见,谢谢。
一、基础
1.1自己创建的activity必须要继承类Activity(或其子类)。在activity里,为了实现activity各种状态的切换,你必须实现指定的回调方法。以下是最为重要的两个回调方法
onCreate():
这是必须实现的回调方法,启动一个 activity时会首先调用此方法。因此,在onCreate()的方法体里,你应该初始化该activity必要的控件。值得注意的是,在这里你必须调用setContentView(Viewview)方法去呈现用户的界面。
onPause():
在用户将要离开activity时调用此方法(指的是此时activity处于半透明状态且没有获取用户的焦点)。通常在这样的状态下,你需要处理用户数据的提交、动画处理等操作。
1.2销毁activity
你可以调用finish()方法去销毁一个activity。同样得,你可以调用finishActivity()方法去销毁一个你刚刚启动的
activity
。
tips
:
在多数情况下,你是不需要显式地调用
finish…()
方法去销毁一个
activity
。在将要讨论到的
activity
生命周期里,你可以知道,
Android
系统会为你管理
activity
的生命周期,所以你并不需要显式销毁
activity
(即调用
finish
类方法)。显式地调用
finish
类方法,会对用户的体验产生不利的影响,除非你确实是不希望用户返回到此
activity
(界面),才去显式调用
finish
类方法。
二、认识
activity
的生命周期
2
、
1
Activity
的生命周期对它的任务、
backstack
和与此有关联的
activity
有着直接的影响
。因此想开发出一个健壮的有弹性的
Android
程序,你需要学会如何去管理
activity
的生命周期(即调用各种回调方法)。
activity
的生命周期主要包含一些三种状态:
(
1
)运行态(
Resumedstate
)
此时
Activity
程序显示在屏幕前台,并且具有焦点,可以与用户的操作进行交互,如向用户提供信息、捕获用户单击按钮的事件并做处理。
(
2
)暂停态(
PausedState
)
此时
Activity
程序失去了焦点,并被其他处于运行态的
otherActivity
取代在屏幕显示,但
otherActivity
程序并没有覆盖整个屏幕或者具有半透明的效果—此状态即为暂停态。处于暂停态的
Activity
仍然对用户可见,并且是完全存活的(此时
Activity
对象存留在内存里,保留着所有状态与成员信息并保持与窗口管理器的连接)。如果系统处于内存不足的情况下,会杀死这个
Activity
。
(
3
)停止态(
StoppedState
)
当
Activity
完全被另一个
otherActivity
覆盖时(此时
otherActivity
显示在屏幕前台),则处于停止态。处于停滞态的
Activity
依然是存活的(此时
Activity
对象依然存留在内存里
,保留着所有的状态和与成员信息,但没有与窗口管理器保持连接),而且它对用户是不可见的,如果其他地方需要内存,系统会销毁这个
Activity
。
处于暂停态
(PausedState)
或者停止态
(Stopped State)
的
Activity
,系统可以通过调用
finish
()方法或者直接终止它的进程来销毁此
Activity
(从内存中清楚此
Activity
对象)。被
finish()
或者销毁的
Activity
再重新打开时,是需要再次初始化此
Activity
的。
2、2
当一个Activity从一种状态转到另一种状态时,会通过调用回调方法来通知这种变化。这些回调方法都是可以重写的,你可以根据程序的的需要来选择重写对应的回调方法。以下列出了Activity生命周期里的基本回调方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
public
class
ExampleActivity
extends
Activity {
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
// The activity is being created.
}
@Override
protected
void
onStart() {
super
.onStart();
// The activity is about to become visible.
}
@Override
protected
void
onResume() {
super
.onResume();
// The activity has become visible (it is now "resumed").
}
@Override
protected
void
onPause() {
super
.onPause();
// Another activity is taking focus (this activity is about to be "paused").
}
@Override
protected
void
onStop() {
super
.onStop();
// The activity is no longer visible (it is now "stopped")
}
@Override
protected
void
onDestroy() {
super
.onDestroy();
// The activity is about to be destroyed.
}
}
|
笔记:在方法体里,必须先调用父类对应的实现方法super.Xxx(),再执行其他的操作(如上面代码所示)。为了习惯,下面也提供一些代码来测试一些这些方法的使用,在博客的最后面。
总的来说,这些回调方法定义了Activity整个生命周期。在生命周期里通过重写这些回调方法,,你可以监控以下下三个嵌套的方法循环。
完整存活的时间:
Activity的完整存活的时间是自第一次调用onCreate()开始,直至调用onDestroy()为止。Activity在onCreate()中设置所有“全局”状态以完成初始化,而在onDestroy()中释放所有系统资源。例如,如果Activity有一个线程在后台运行从网络下载数据,它会在onCreate()创建线程,而在 onDestroy()销毁线程。
可见状态的时间:
Activity的可见状态是自onStart()调用开始直到相应的onStop()调用结束。在此期间,用户可以在屏幕上看到Activity,尽管它也许并不是位于前台或者也不与用户进行交互。在这两个方法之间,我们可以保留用来向用户显示这个Activity所需的资源。例如,当用户不再看见我们显示的内容时,我们可以在onStart()中注册一个BroadcastReceiver来监控会影响UI的变化,而在onStop()中来注消。onStart() 和 onStop() 方法可以随着应用程序是否为用户可见而被多次调用。
显示在前台的时间:
Activity的前台显示是自onResume()调用起,至相应的onPause()调用为止。在此期间,Activity位于前台最上面并与用户进行交互。Activity会经常在暂停和恢复之间进行状态转换——例如当设备转入休眠状态或者有新的Activity启动时,将调用onPause() 方法。当Activity获得结果或者接收到新的Intent时会调用onResume() 方法。
2.3
下图显示了这三个循环之间的状态转换(其中写在长方形里的是你可以用来重写并实现对应操作的方法)。
同样的,以下面的表格来描述生命周期里的回调方法,并包含了更加详细的信息。
方法 |
描述 |
是否可以终止 |
下一个方法 |
||
当Activity程序启动之后会首先调用此方法。在这个方法体里,你需要完成所有的基础配置——创建视图,连接数据库并将数据绑定到list列表中,等等。这个方法会传递一个保存了此Activity上一状态信息的Bundle对象。紧随其后的方法总是 |
不可以 |
|
|||
处于停止态的Activity调用此方法,可以让此Activity重新显示在前台。 紧随其后的方法总是 |
不可以 |
|
|||
在此Activity可见(显示在前台)之前调用。 如果接着是显示在前台,紧随其后的方法是 |
不可以 |
|
|||
在与用户进行交互之前调用此方法,这一时刻Activity位于activity栈的栈顶,在等待用户的操作(输入数据或点击按钮等)。紧随其后的方法是 |
不可以 |
||||
当启动其他activity时调用此方法。在这个方法体里,通常用于提交未保存的数据、停止动画/视频和处理其他占用CPU资源的程序,等等。同时在这个方法体里处理的都是一些迅速快捷的操作,因为下一个activity会在onPause() 如果此Activity重新回到前台显示,则紧随其后的方法是 |
可以 |
|
|||
当Activity不可见时调用此方法。这个方法的调用时刻是在Activity需要销毁或者被其他otherActivity取代且覆盖此Activity在前台显示时调用。 如果此Activity重新显示在前台,紧随其后的方法是 |
可以 |
|
|||
Activity被销毁时调用此方法。这是Activity生命周期里最后调用的一个方法。这个方法的调用可以发生在activity调用了finish()方法之后,或者是系统为了节省空间而销毁了此Activity的实例。你可以使用isFinishing()方法来区分这两种情况。 |
可以 |
—— |
“是否可以终止”是指系统是否可以在此方法执行完后直接销毁该Activity的实例(没有再去执行此Activity内的其他代码)。如上表所示,onPause(),onStop(),和onDestroy()三个方法
是可以终止的。同时从状态图(上图)中可以知道
onPause()方法是这三个方法中第一个调用的,自一个
Activity
创建开始,直到此
Activity
终止或销毁,
onPause()
是最后一个保证会被调用的方法(如在突发情况下系统回收内存,
onStop()
和
onDestroy()
就不会被调用)。因此,你应该在
onPause()
方法里保存一些关键的数据(如用户编辑的内容),所谓“关键“就是让你有选择地去保存一些重要的数据,因为
onPause()
方法执行时间过长,会延迟下一状态的切换,进而影响了用户的体验。
附:在上表注明不可以被终止的方法也可能会被系统终止,不过这一情况只会在一些极端的情况下发生。
三、保存Activity的状态信息
在前文提到过,处于暂停态的和停止态的Activity,其对应的状态的状态与成员信息依然保留在内存里。那么这些信息又是如何保存的??我们又应该如何去利用这些信息??
在暂停状态下的activity,因其activity信息完整保存在内存里且保持与窗口管理器的连接,所以可以直接调用onRestart()方法还原activity。
用户经常会使用返回按钮返回上一个界面(Activity),用户当然是希望上一个界面(Activity)和他原来看到或编辑的一样,在这种情况下你就需要使用之前已经保存好的状态信息和成员变量来还原上一个Activity。若要保存一个Activity的状态信息和成员变量,则需要实现回调方法onSaveInstanceState()。
onSaveInstanceState()会在执行
onStoped()
方法之前调用,这个方法有一个参数
Bundle
,可以以“名称
-
值”的形式保存
activity
的信息(如使用
putString(),putInt()
方法)。接着在需要还原
activity
时,系统会调用
onCreat()
或者
OnRestoreInstanceState(),这两个方法都传入一个以保存了activity信息的Bundle对象,通过提取Bundle对象的信息来恢复activity。如果没有信息需要保存到Bundle对象,那传递给这两个方法的将是空的Bundle对象(刚开始初始化一个activity时其实就是这种情况)。如下图所示:
其实,即使你没有实现回调方法onSaveInstanceState(),
系统也会执行默认的
onSaveInstanceState()。
值得注意的是,系统会为每个
View
组件执行相对应的
onSaveInstanceState(),这可以使每一个组件保存自己相对应的信息。在
Android
里,几乎所有的控件都实现了这个方法,因此在界面产生的可见变化都会自动保存下来,也就可以还原
activity
。举个例子:在
EditText
输入的内容或者
CheckBox
的选择,都会自动保存下来。而你所需要做的就是为需要保存信息的控件提供一个
id
(在
XML
文件里的属性
android:id
),如果你没有为控件提供id,那系统是不会自动保存这些信息的。
下面给出一些例子参考一下onSaveInstanceState()和OnRestoreInstanceState()方法的使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@Override
protected
void
OnSaveInstanceState(Bundle outState)
{
outState.PutString(
"myString"
,
"HelloXamarin.Android OnSaveInstanceState"
);
outState.PutBoolean(
"myBool"
,
true
);
base.OnSaveInstanceState(outState);
}
@Override
protected
void
OnRestoreInstanceState(Bundle savedState)
{
base.OnRestoreSaveInstanceState(savedState);
var myString =savedState.GetString(amyStringa);
var myBool =GetBoolean(amyBoola);
}
|
附:如果需要强制控件不保存对应的信息,可以在布局文件设置android:saveEnabled =
“
false
”,或者使用控件对象的
setSaveEnabled()方法。
尽管系统默认执行onSaveInstanceState()保存对应控件的信息,有时候你需要实现这个方法去保存一些额外的变量。例如:你需要去保存一些在这个activity生命周期里会改变的变量(指控件信息之外的变量),这些会改变的变量系统是默认不保存的。
需要注意的是:onSaveInstanceState()方法不保证一定会被调用,所以在这个方法里你只应该保存一些临时变量(如
UI
的状态),而不要去保存一些需要持久化的数据。相反,你应该在
onPaused
()方法里保存需要持久化的数据(例如保存到数据库里的数据)。
tips
:
Android
系统上
Back
按钮和
Home
按钮的区别,尽管他们都可以导航到另外一个
otherActivity
(可以是其他程序的),可他们的作用原理是不一样的。在界面(
Activity
)上点击
Back
按钮,系统会认为这个
Activity
已完成其对应的实现逻辑,则调用对应的方法销毁此
Activity
;可当点击
Home
按钮时,系统会认为这个
Activity
还没有完成对应的逻辑,则系统并不会销毁这个
Activity
,而是让其处于停止态(
Stopped State
)
.
四、协调各个
Activity
当
ActivityA
启动
ActivityB
时,这两个
Activity
都需要进行状态的切换。当
ActivityB
创建的时候,
ActivityA
会切换到暂停态或者停止态(当
ActivityA
依然可见是切换到暂停态,不可见则切换到停止态)。假设这两个
Activity
共享某些存储在磁盘的数据,这样很有必要去知道,在
ActivityB
创建完成之前,
ActivityA
都还没有切换到停止态
(StopppedState)
。
当两个
Activity
处于源于同一个
App
,又是一个启动另外一个
Activity
的时候,其生命周期的回调方法是已经定义好的了。一下是这两个
Activity
状态切换个回调方法的调用顺序。
1.
执行
ActivityA
的
onPaused
()方法
2.
依次执行
ActivityB
的
onCreate()
,onStart()
,和onResume()
方法(此时
ActivityB
显示在前台,获得焦点)。
3.
然后,如果
ActivityA
变得不可见,则执行
ActivityA
的
onStopped()
方法。
根据这些方法调用顺序,可以知道:如果需要在
ActivityA
保存数据到数据库,接着让
ActivityB
读取,那么你应该
onPaused
()方法里执行持久化操作,而不是在
onStopped
()方法里。
附录:
activityLifecycle
的代码和运行效果图。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
public
class
ActivityA
extends
Activity {
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
System.out.println(
"ActivityA-->onCreate()"
);
}
@Override
protected
void
onStart() {
super
.onStart();
System.out.println(
"ActivityA-->onStart()"
);
}
@Override
protected
void
onRestart() {
super
.onRestart();
System.out.println(
"ActivityA-->onRestart()"
);
}
@Override
protected
void
onResume() {
super
.onResume();
System.out.println(
"ActivityA-->onResume()"
);
}
@Override
protected
void
onPause() {
super
.onPause();
System.out.println(
"ActivityA-->onPause()"
);
}
@Override
protected
void
onStop() {
super
.onStop();
System.out.println(
"ActivityA-->onStop()"
);
}
@Override
protected
void
onDestroy() {
super
.onDestroy();
System.out.println(
"ActivityA-->onDestroy()"
);
}
public
void
startDialog(View v) {
Intent intent =
new
Intent(ActivityA.
this
, DialogActivity.
class
);
startActivity(intent);
}
public
void
startActivityB(View v) {
Intent intent =
new
Intent(ActivityA.
this
, ActivityB.
class
);
startActivity(intent);
}
public
void
finishActivityA(View v) {
ActivityA.
this
.finish();
}
}
Action
|
DialogActivity代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
public
class
DialogActivity
extends
Activity {
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_dialog);
System.out.println(
"DialogActivity-->onStart()"
);
}
@Override
protected
void
onStart() {
super
.onStart();
System.out.println(
"DialogActivity-->onStart()"
);
}
@Override
protected
void
onRestart() {
super
.onRestart();
System.out.println(
"DialogActivity-->onRestart()"
);
}
@Override
protected
void
onResume() {
super
.onResume();
System.out.println(
"DialogActivity-->onResume()"
);
}
@Override
protected
void
onPause() {
super
.onPause();
System.out.println(
"DialogActivity-->onPause()"
);
}
@Override
protected
void
onStop() {
super
.onStop();
System.out.println(
"DialogActivity-->onStop()"
);
}
@Override
protected
void
onDestroy() {
super
.onDestroy();
System.out.println(
"DialogActivity-->onDestroy()"
);
}
public
void
finishDialog(View v) {
DialogActivity.
this
.finish();
}
}
|
其他代码类似,就不一一张贴了。
附件:http://down.51cto.com/data/2363360