(内容:如何创建、使用activity; activity生命周期。)
Activity
Activity 是一个为用户提供交互接口的组件,每个activity都会有一个window来显示自己的界面。 应用可以由多个互相“弱关联”的activity组成,activity可以启动另外一个activity, 有activity启动的时候,当前的就会被暂停,系统把被暂停的activity存储在一个FILO(先进后出)的栈中,当用户点击“back”时,位于栈顶的activity就会重新被显示出来。
Activity 提供一系列的接口,在生命周期运行到特定的阶段时会通知相应的接口,用户在这些回调接口中做当前阶段的处理。例如,在create时初始化应用的资源,stop时作资源的释放。
1 创建Activity
创建一个activity必须继承为Activity的子类,并覆盖所需要生命周期的回调方法。比较重要的2个方法:
onCreate(): 系统在创建activity时会调用,必须要覆盖的方法。应该在此阶段做初始化工作,layout一定要在这里被初始化:调用setContentView() 设置activity的界面。
onPause(): 用户离开这个activity时系统调用的第一个方法,鉴于用户不一定会再返回这个activity,应该做数据持久化的处理。
生命周期的其他部分会在后面继续讨论。
1.1 建立用户界面
用户界面由含有层级关系的一个或多个View组成,每一个View控制屏幕的一个矩形区域,且可以相应用户的操作。术语Widgets表示用户可见或可交互的View,Layout 则是ViewGroup,它包含的view提供布局的规则。
android已经提供了一系列的组件如button、textview等,我们可以直接使用,也可以继承View 或 ViewGroup,实现特定功能的控件。
将布局传递给activity一般的做法是在xml中定义自己的界面,然后使用setContentView()布局。
1.2 在Manifest中声明activity
Activity必须在所属应用的Manifest.xml中声明,不然系统会找不到,最简单的声明可以按照以下格式:
<manifest ... >
<application ... >
<activity android:name=".ExampleActivity" />
...
</application ... >
...
</manifest >
android:name对应这个activity的路径,包名和java名。还有其他可选的属性如label,theme等。
在声明之后,还可以为activity加上其他属性,如果这个activity是用在显示在桌面上的主程序,就应该加上以下内容,不然程序找不到主入口了:
<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
2 启动Activity
在一个activity中,使用startActivity()启动另外一个activity,为了注明要跳转到哪里activity,需要使用Intent:
//从当前的activity跳到“YourActivity”
Intent intent = new Intent(this, YourActivity.class);
startActivity(intent);
除了直接指定class名,android提供了另外一种特殊的方式:
你的应用可能需要别的程序为你完成一些特定操作,只要为Intent指定一个Action,系统就会为你找到接收这个action的activity。(Intent的最精华的作用在于此,实现松耦合)
例如你的程序需要发送一封邮件给指定的收件人,intent需要一个action和 收件人的列表作为data,Email编辑界面会为你加载这些数据,这里的recipientArray会被读取并显示在Email的收件人编辑框中:
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL,recipientArray);
startActivity(intent);
2.1 启动带有返回结果的activity
startActivity()只是告诉系统要启动一个activity, 但有些情况下,我们还需要启动的activity为我们完成一项工作后返回结果和数据,可以用以下方法:
startActivityForResult(Intent i, int requestCode); //requestCode 标记这个activity
例子,需要用户从电话本选取一个联系人并返回给当前activity做处理:
private void pickContact() {
// Create an intent to "pick" a contact, as defined by the content provider URI
Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT_REQUEST);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// If the request went well (OK) and the request was PICK_CONTACT_REQUEST
if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) {
// Perform a query to the contact's content provider for the contact's name
Cursor cursor = getContentResolver().query(data.getData(),
new String[] {Contacts.DISPLAY_NAME}, null, null, null);
if (cursor.moveToFirst()) { // True if the cursor is not empty
int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);
String name = cursor.getString(columnIndex);
// Do something with the selected contact's name...
}
}
}
3 关闭activity
finish() 和 finishActivity()都可以关闭一个activity,但google建议:除了必须时,不要直接调用这些接口,应该交由系统统一管理生命周期。
4 管理生命周期
一个activity的生命周期直接受到其他activity、当前任务或back stack的影响,通过生命周期的接口对activity进行管理,可以建立更加健壮和灵活的程序。
覆盖生命周期的回调方法
以下回调方法对应着生命周期的几个状态:
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.
}
}
如果覆盖以上的全部方法,我们就可以完整地管理activity 生命周期的3个阶段(但实际上某些时候只需要其中几个),在不同阶段应该做相应级别的处理:
- 从onCreate() 到 onDestroy()是一个完整的周期 。 应该在onCreate()做初始化(layout等),在onDestroy()中释放所有占用的资源(如正在工作的线程、bitmap等)。
- 从onStart()到 onPause()被调用前 属于可见的周期。用户可以看见activity的界面并与之交互。如果当前界面不再可见,onStop()将会被调用。在这2个方法之间,应该管理和UI显示相关的数据资源。如:onStart()注册一个receiver监听数据的变化,在onStop()时应注销它,因为界面已经不可见,不需要再更新。
- 从onResume()到 onPause()被调用,属于前台(foreground)的周期。activity处于所有其他activity之前,并能接收用户输入。因为activity经常被高频率的切换,前台activity被转入后台(如弹出一个非全屏的dialog),这2个方法应用于处理一些轻量级的操作,防止界面切换出现卡顿。
生命周期的经典图示:
生命周期方法的总结:
onCreate: activity被创建时调用。初始化静态数据的操作:创建view,为list绑定数据等。它有一个Bundle作为参数,存放 着这个activtiy之前的状态(onSaveInstanceState())。之后调用的一定是onStart()。
onRestart: activity被stop后,还原时调用。之后调用的一定是onStart()。
onStart: 在activity显示在屏幕之前调用。如果activity转到前台会调用onResume(),如果界面被遮挡则进入onStop()。
onResume(): 在可以和用户交互之前调用。 activity已经被置于栈顶。 onPause()在其后调用。
onPause(): 在另一个activity即将resume时被调用。一般用来保存数据和停止一些消耗CPU的操作等。鉴于界面正 在跳转,为了不阻塞,这里的操作应该越快完成越好。 activtiy若回到显示状态将会调onResume(), 否则 随后调用onStop()让它消失在屏幕上。
onStop(): 在界面完全被遮挡住前调用。 这时,可能activity即将被destroy,或者其他activity resume并遮住了它。 activtiy若将重新显示则调用onRestart(), 否则进入onDestroy() 将其毁灭。
onDestroy(): activity即将被灭掉了。这是最后一个被调用的周期方法。 导致destroy的可能是用户指定finish(), 或者系统 为了节省空间。 isFinishing()可以区分这两种情况。
注意:onPause()方法其实是系统一定会调用的最后一个生命周期方法,onStop(), onDestroy()都不保证一定能调到,所以重要的事情应该在onPause()里面完成(保存数据等),且选择必须保留的数据,避免阻塞下一个activity。
5 保存activity状态
activity 的回调方法 onSaveInstanceState() 可以用于保存activity状态,方法提供Bundle参数给我们保存数据,如果系统kill掉了这个activity,用户return回去的时候,我们可以通过onCreate()(或者onRestoreInstanceState())的Bundle参数提取出这些数据。
onSaveInstanceState()默认保留各种View的显示状态(checkbox是否勾上等),我们需要做的是保存与界面绑定的一些变量值,如记录checkbox值的数组,并且确保layout中的重要view都有自己的id,否则它的状态无法保存。如果覆盖此方法,应该在开始便调用super.onSaveInstanceState(),因为它默认会帮组我们记录view的状态。
来源:oschina
链接:https://my.oschina.net/u/868131/blog/91341