扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
Activity 是我们在学习android 的时候最先接触到的东西,也是android 开发过程中不可少的组件。而 在我们android 学习中,对activity 有个全面的认识是很重要的。本人在学习android 以来,对activity 也是又爱又恨,所以特意做了个总结,希望能对 那些 activity 认识还不够的“同鞋”一些帮助。
七星网站制作公司哪家好,找创新互联公司!从网页设计、网站建设、微信开发、APP开发、自适应网站建设等网站项目制作,到程序开发,运营维护。创新互联公司自2013年起到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选创新互联公司。
内容提要
1、Activity 的概念
2、Activity 类继承关系
3、Activity 的生命周期
4、Activity 横竖屏切换时生命周期变化
5、Activity 启动模式
6、Activity 之间通信数据传递
7、Activity 的回收与数据保存
内容详情
1、Activity 的概念
在谷歌给的官方Android Api文档中,是这么描述 Activity中的:
一个 activity 是一个单一的,聚焦了用户可以做的事情。几乎所有的 activity 都与用户进行交互,因此 activity 需要关注创建一个窗口,可以通过 setContentView(int) 来更新替换 UI 视图界面。activity 往往是以全屏方式呈现给用户的,你也可以通过设置主题或将activity嵌入其他activity 的方式来改变。
2、Activity 类继承关系
通过这张类图,我们可以看到,activity 是继承于 ContenttextThemeWrapper 类的,是它的直接也是唯一子类。
而activity 的直接子类 则有ActivityGroup、AliasActiviyt、ExpandableListActivity和 ListActivity,其中常用的有 ListActivity (后面再讲List 相关用法时,会讲下ListActivity的相关用法)。
3、Activity 的生命周期
相信这张图你已经见过很多次了吧,经典永远是值得学习的。下面我们就来好好学习下经典。
所有的 activity 都会实现两个方法:onCreate() 和 onPause()方法。
下面就来具体讲讲图中的各个方法详情和都在什么情况下调用:
onCreate: 在这里创建界面,做一些数据的初始化工作
onStart: 到这一步变成用户可见不可交互的
onResume: 变成和用户可交互的,(在activity 栈系统通过栈的方式管理这些个Activity的最上面,运行完弹出栈,则回到上一个Activity)
onPause: 到这一步是可见但不可交互的,系统会停止动画等消耗CPU 的事情从上文的描述已经知道,应该在这里保存你的一些数据,因为这个时候你的程序的优先级降低,有可能被系统收回。在这里保存的数据,应该在onResume里读出来,注意:这个方法里做的事情时间要短,因为下一个activity不会等到这个方法完成才启动
onstop: 变得不可见,被下一个activity覆盖了
onDestroy: 这是activity被干掉前最后一个被调用方法了,可能是外面类调用finish方 法或者是系统为了节省空间将它暂时性的干掉,可以用isFinishing()来判断它,如果你有一个ProgressDialog在线程中转动,请在onDestroy里把他cancel掉,不然等线程结束的时候,调用Dialog的cancel方法会抛异常的。
注:onPause,onstop, onDestroy,三种状态下 activity都有可能被系统干掉。
正常启动activity:onCreate-> onStart -> onResume(启动)
正常退出activity: (启动)-> onPause-> onStop -> onDestroy(退出)
activity 启动后被打断,进入一个新全屏activity:
(启动)-> onPause->onStop
恢复时:onStart->onResume
activity 启动后被打断,进入一个不是全屏的窗口,如Dialog之类的:
(启动)-> onPause
恢复时:onResume
4、Activity 横竖屏切换时生命周期变化
在android 程序清单中声明activity 时我们可以设置 activity在横竖屏切换时的生命周期变化,具体情况如下:
不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次。
设置Activity的android:configChanges="orientation"时,切横,竖屏时生命周期只会执行一次。
设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用声明周期,只会执行onConfigurationChanged方法。
5、Activity 启动模式
我们知道在继承一个activity类时,当我们要将自己写的 activity启动的时候,我们需要在 androidManifest.xml 程序清单里面,声明所要启动的 activity,而在声明 activity 的同时 我们可以设置activity 的启动模式,launchModel = "...",在android 系统中 ,activity 有四种启动模式,而系统默认是 standard,启动模式在某些需求的情况下可以方便系统 对activity 的管理。
下面说解讲下四种启动模式的各自的特点和区别:
standard:
默认模式,可以不用写配置。
activity在同一个任务栈,
每启动一个activity,都会默认创建一个新的实例。
因此,在这种模式下,可以有多个相同的实例,也允许多个相同Activity叠加。
singleTop:
activity在同一个任务栈,
当要启动的activity处于栈顶时,重复启动之前已创建的实例;
当要启动的activity 不处于栈顶时,会创建新的实例
singleTask:
activity在同一个任务栈,只在一个实例,若创建了将不重复创建;
在启动已在栈里面有的activity时(由栈顶的activity(B) 跳转到下面的 activity (A)时),会将在A上面的activity 一直弹出,一直到A。
singleInstance:
每个activity是独立任务栈,且只放一个activity实例, activity的之间的切换会在几个不同任务栈之间跳转。
6、Activity 之间通信数据传递
在平常的android 开发过程中, 很多活动界面之前是需要传递数据的,也就是说在activity之间是需要传递数据,而数据怎么传递,传递什么样的数据,这些都要有一定的了解。
下面详细介绍:
1、简单数据采用 Intent 来传递
A->B
A中 绑定数据:
Intent intent = new Intent( this, MyReceiver.class);
intent.putExtra( "data", "data from A");
StartActivity(intent);
B中 接收数据:
String data = intent.getStringExtra( "data");
2、数据包采用Bunde 来传递
A->B
A中 绑定数据:
Bundle b = new Bundle();
b.putString("string","String data from A");
b.putInt("int","Int data from A");
b.putBoolean("boolean","Boolean data from A");
Intent intent = new Intent( this, MyReceiver.class);
intent.putExtra("datas",b);//intent.putExtra(b);
B中接收数据:
Bundle b = getIntent.getExtras("datas")//b = getIntent().getExtras();
String datastr = b.getString("string","default");//default为缺省值
3、对象的传递
A->B ,class User (name,age)
1》Serializable java语言提供 ,效率较低
User中:继承Serializable , class User implements Serializable
A中: intent.putExtra("user",new User());
B中: User user = (User)getIntent().getSerializableExtra("user");
2》Parcelable 专门面向移动端,效率较高
User中:继承Parcelabe , class User implements Parcelable
实现两方法:
public int describeContents(){return 0}
public void writeToParcel(Parcel dest, int flags){
dest.writeBundle()//这样可以传递很多相同类型数据了
dest.writeString(getName());
dest.writeInt(getAge());
}
public static final Creator
public User createFromParcel(Parcel source){
source.readBundle();//
return new User(source.readString(),source.readInt());
}
public User[] newArray(int size){
return new User[size ];
}
}
A中: intent.putExtra("user",new User());
B中: User user = (User)getIntent().getParcelableExtra("user");
3、从被启动的activity 传递数据到 主activity(返回传递数据)
A->B,B->A
B中:返回时监听:
String bData;
Intent intent = new Intent();
intent.putExtra("dataB",bData );
setResult(1,intent);//返回状态码可以自行设定
finish();
A中:在启动时:
startActivityForResult(intent, 0);//返回的请求码
实现方法:onActivityResult(int requestCode,int resultCode,Intent data)
onActivityResult(int requestCode,int resultCode,Intent data){
if(requestCode == 0){
if(resultCode == 1)
String s = data.getStrignExtra("dataB");
}
}
4、还有一种懒汉方法来传递数据,进行通信如设置一个公共类,在公共类中,将要传递的数据声明为 公有静态的(public static ),这样就可以在直接在activity之间进行通信了。当然这种数据也可以放在 application 这个全局的 类里面。这种方法通常是用来判断 是否登陆超时,或是一些全局的配置等等。
7、Activity 的回收与数据保存
之前在讲解 activity 生命周期的时候,我们就已经知道了,activity 在某些情况下会被系统干掉的,如果这个activity 又在做一些重要的数据,举一个简单的例子, 我们在登录一个时,只填写了一部分,临时离开了这个界面,当我们返回时,如果又需要重新在填写全部的数据,这是不是有点坑,,,严重影响用户体验。
当然这只是举的一个小例子,或许有点不恰当,但我们确实是需要在系统回收 activity ,activity被异常干掉的时候保存当前的用户数据 ,而在再次打开或恢复时,应当能还原当初的数据。
因为 activity 的切换,所以当用户在再次切换回原来的 activity的时候,原先的 activity 有两种情况:一种是被回收,一种是没有被回收,
被回收的A就要重新调用onCreate()方法,不同于直接启动的是这回onCreate()里是带上参数
savedInstanceState,没被收回的就还是onResume就好了。
savedInstanceState是一个Bundle对象,你基本上可以把他理解为系统帮你维护的一个Map对象。在onCreate()里你可能会用到它,如果正常启动onCreate就不会有它,所以用的时候要判断一下是否为空。
前面在生命周期也讲过,我们可以在onPause 方法中 保存数据,而在 onResume 方法中恢复数据。
其实谷歌早就考虑到了关于 activity 异常退出,被系统回收的 的 数据 保存与恢复相关的问题。
那就是这两个方法: onSaveInstanceState(Bundle outState) 和 onRestoreInstanceState(Bundle savedInstanceState) 方法,这两个 前者是负责在activity被异常干掉之前保存数据,而后者是负责恢复数据。
注:
onSaveInstanceState()方法,在正常情况下就不会被调用的,只有当 activity 发生异常时才会被调用。
onRestoreInstanceState()方法,系统会调用,其实也是不需要我们人为去干涉的。
我们接着看,注意 onSaveInstanceState(Bundle outState )方法的参数,是的,是 Bundle 类型的,还记得前面提到过的 数据传递部分吗,Bundld 就可以保存大多数的数据。 现在或许有人说 onRestoreInstanceState() 方法我们可以不去多管,总感觉心里不踏实,是吧,那我们在哪个地方 将 outState 里面保存的数据拿出来呢?
我们再看看 onCreate(Bundle savedInstanceState) ,是不是发现什么了,这个参数,也是Bundle 类型的,其实这里的 savedInstanceState 就是之前保存的 outState,而我们可以在onCreate 方法中取消之前 保存的数据。
最后问的归纳如下:
保存数据:
void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putLong("id",1234567890); }
判断 和 恢复 数据:
void onCreate(Bundle savedInstanceState){ .......... if(savedInstanceState != null){ ..... } }
好了,到这里我们对 activity 已经有了个大概的理解了,而博客也到这里结束了。这是 本人 第一次写的 关于 android 的文章 ,从自己学习android 以来,中间有苦有甜,有笑有泪,不容易啊,今天在我即将走出校园,即将用 android 来谋生的同时,写下这篇博客,希望能在android这条路上走得越来越宽,越来越远。
注:这博客是总结型的,中间有我自己对 android api 的翻译,同样其中不免有些知识点是有和其他文章有相通的,所以如果有失礼或者是有不是很恰当的地方,还请前辈们见谅。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流