在正文开始之前,我给大家来个段子:
乌龟正在河里洗澡被癞蛤蟆看见了,
乌龟:没见过像我这样的美女吗?看你眼珠子都快要蹦出来了。
癞蛤蟆:妹,你就别逗我了,没有看见我身上已经起鸡皮疙瘩了吗?
只是想让大家放松下,作为一名程序猿不要一直紧绷着大脑。
相信大家对 Activity都不陌生,或多或少都有自己的理解,我会从什么是 Activity,创建一个 Activity,实现一个用户界面,如何在清单文件声明,启动一个新的 Activity,关闭一个 Activity 以及 Activity的生命周期,Activity的状态保存.
一、什么是Activity
一个活动是一个应用程序组件,它提供了一个屏幕,用户可以交互为了做某件事,如拨电话,拍照,发送电子邮件,或查看地图。每个活动都将画它的用户界面的一个窗口。窗户通常充斥屏幕,但可能比屏幕小,浮在其他窗口的顶部。
二、创建一个Activity
你创建的类必须继承Activity或者继承Activity的子类,你需要实现回调方法。系统调用时,其生命周期的不同状态之间的转换,如停止,恢复或销毁。最重要的两个回调方法:
onCreate()
Activity被创建时调用,调用setContentView()来定义用户界面的布局。通常setContentView(R.layout.activity_main);
当然你也可以setContentView(View view)
来展示你的界面。
onPause()
用户离开Activity时被调用,任何的修改都应该被提交(通常用于ContentProvider保存数据)。
三、实现一个用户界面
用户界面提供了一个试图,每个视图就是一个窗口,可以响应用户交互。例如,一个视图可能是一个按钮,当用户触摸它启动一个动作。
Android提供了许多现成的视图,您可以使用它们来设计和组织你的布局。比如一个按钮,文本框,复选框,或者只是一张图片。“布局”视图来自ViewGroup提供一个独特的子视图的布局模型,如线性布局,网格布局,或相对布局。你也可以继承View和ViewGroup类来自定义布局或控件将它们应用到你的Activity中。
四、清单文件声明
你创建的Activity必须在清单文件中声明:
<activity android:name=".MainActivity"> //全名是包名+类名
<intent-filter> //意图过滤器
<action android:name="android.intent.action.MAIN" />//动作
<category android:name="android.intent.category.LAUNCHER" /> //类别
</intent-filter>
</activity>
以下声明表示该Activity为程序入口,并且action 和category 的值不能被改变。
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
//决定应用程序是否显示在程序列表里
如果声明的Activity并不是程序入口,action 的name的值可以随意改变,规范写法(包名+类名),category 的name的值为.DEFAULT或.LAUNCHER,在后面我会具体讲解下它们的区别。
<action android:name="com.github.wens.LoginActivity" />
<category android:name="android.intent.category.DEFAULT" />
五、启动一个新的Activity
通过一个Intent意图,来启动一个新的Activity.
1、显示意图
Intent intent = new Intent(this, IndexActivity.class);
startActivity(intent);
2、隐示意图
Intent intent=new Intent();
intent.setAction("com.github.wens.IndexActivity");
startActivity(intent);
这里setAction就是AndroidManifest.xml清单文件下 action 的name值.注意:如果使用隐示意图启动Activity,在清单文件中category的类别为.DEFAULT,不然会导致匹配失败。
然而,你的应用程序可能也要执行一些操作,如发送短信、发送邮箱、拨打电话等,使用上面的方法是不能够实现的,怎么办呢?下面我以发送邮箱为例:
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);
当然你除了发送邮箱,还可以发送文本EXTRA_TEXT,发送图片EXTRA_STREAM等。
有些时候你需要接收启动新界面返回的结果。这个时候你就要使用startActivityForResult() (代替 startActivity()),下面我举个例子来说明:
如上图所示,界面A需求界面B返回的数据,在界面A:
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(A.this, B.class);
startActivityForResult(intent, 1); //requestCode
}
});
并且我们在onActivityResult()处理返回结果:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) {
if (resultCode == 2) {
String text = data.getStringExtra("data");
tv.setText(text);
}
}
}
在B界面:
@Override
public void onBackPressed() {
//super.onBackPressed();
Intent intent = new Intent();
intent.putExtra("data", et.getText().toString());
setResult(2, intent); //resultCode
finish();
}
六、关闭一个Activity
调用finish(),你也可以调用finishActivity()。
七、Activity的生命周期
下面我对每个方法具体讲解下:
onCreate()
第一次被创建时调用。我们可以在这个方法里面创建视图,绑定组件ID,等等。总是跟着onStart()。
onRestart()
在onStop()方法后被调用,总是跟着onStart()。
onStart()
总是跟着onResume()。
onResume()
用户交互,处于栈顶,总是跟着onPause()。
onPause()
当程序启动新的Activity,该方法通常用于提交持久化数据,保存数据,停止动画和其他消耗的CPU的操作等等。不适合做耗时的操作,否则会引起界面卡顿。总是跟着onStop()。
onStop()
用户不可见,因为一个新的Activity已经覆盖它,总是跟着onDestroy()或者onRestart()。
onDestroy()
消亡时被调用。
八、状态保存
一般来说, 调用onPause()和onStop()方法后的activity实例仍然存在于内存中, activity的所有信息和状态数据不会消失, 当activity重新回到前台之后, 所有的改变都会得到保留.
但是当系统内存不足时, 调用onPause()和onStop()方法后的activity可能会被系统摧毁, 此时内存中就不会存有该activity的实例对象了. 如果之后这个activity重新回到前台, 之前所作的改变就会消失. 为了避免此种情况的发生, 我们可以覆写onSaveInstanceState()方法. onSaveInstanceState()方法接受一个Bundle类型的参数, 我们可以将状态数据存储到这个Bundle对象中, 这样即使activity被系统摧毁, 当用户重新启动这个activity而调用它的onCreate()方法时, 上述的Bundle对象会作为实参传递给onCreate()方法, 我们可以从Bundle对象中取出保存的数据, 然后利用这些数据将activity恢复到被摧毁之前的状态.
说了这么多,我们还是来看代码:
在onCreate()
if (savedInstanceState != null) {
String data = savedInstanceState.getString("data");
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("data", "test");
}
注意:onSaveInstanceState()方法并不是一定会被调用的, 因为有些场景是不需要保存状态数据的. 比如用户按下BACK键退出activity时, 用户显然想要关闭该activity, 此时是没有必要保存数据以供下次恢复的, 也就是onSaveInstanceState()方法不会被调用. 如果调用onSaveInstanceState()方法, 调用将发生在onPause()或onStop()方法之前.
onSaveInstanceState()默认实现保存UI控件的状态数据,我们需要额外的数据时,就需要重写onSaveInstanceState().注意:在onSaveInstanceState()不适合做持久化数据的保存,适合保存UI控件状态,和成员变量等。
引发activity摧毁和重建情形
除了系统处于内存不足的原因会摧毁activity之外, 某些系统设置的改变也会导致activity的摧毁和重建. 例如改变屏幕方向, 改变设备语言设定, 键盘弹出等.
如果文中有什么不对的地方,还请大家给于指出,谢谢。