android初学者必须掌握的Activity状态的四大知识点(必读)
这几天一直都在捣鼓android的知识点,兴趣班的老师,讲课太过深奥,天(想到什么就见什么,后后面完全不想听),最后自己找资料总结了在android学习中很重要的一个组件activity,那就开始吧!
第一:掌握activity的四种状态及什么时候触发
首先我们要知道什么是activity,简单来说activity其实就是一个屏幕的显示页面。(简单的阐述)
我们知道activity是由activity栈进管理,当来到一个新的activity后,此activity将被加入到activity栈顶,之前的activity位于此activity底部。
acitivity一般意义上有四种状态:
1、running状态: 一个新的activity启动入栈后,它在屏幕的最前端,处于栈的最顶端,此时它处于可见并可和用户交互的激活状态,android试图尽最大可能保持它活动状态,杀死其它activity来确保当前活动activity有足够的资源可使用。当另外一个activity被激活,这个将会被暂停。
2、paused状态:当activity处于此状态时,此时它依然与窗口管理器保持连接,系统继续维护其内部状态,它仍然可见,但它已经失去了焦点,故不可与用户交互。
3、stopped状态: 当activity 不可见时,activity处于stopped状态。当activity处于此状态时,一定要保存当前数据和当前的ui状态,否则一旦activity退出或关闭时,当前的数据和ui状态就丢失了
4、killed状态: activity被杀掉以后或者被启动以前,处于killed状态。这是activity已从activity堆栈中移除,需要重新启动才可以显示和使用。
对四种状态的一个总结:running状态和paused状态是可见的,stopped状态和killed状态时不可见的,当然starting是有系统自身自动创建,而且每一个活动( activity )都处于某一个状态,对于开发者来说,是无法控制其应用程序处于某一个状态的,这些均由系统来完成。
但是当一个活动的状态发生改变的时候,开发者可以通过调用 onxx() 的方法获取到相关的通知信息。
接下来讲下各种状态在何时触发:
1、running状态:
期间触发的函数及顺序为: oncreate() ->on start() -> onresume()。
注意:
1.1:oncreate()只有在该activity是第一次被创建时才会被调用,主要是负责activity的一般性的初始化设置,包括视图的创建,数据的绑定等等。
需要注意的是若之前有冻结的state(即系统对该activity调用过onsaveinstancestate()函数),则可以通过其 bundle 参数进行state恢复。
1.2:on start()是当activity正在变为可见状态时才会被调用。一般地在此期间可以注册一个广播等等。
1.3:onresume()是在该activity将要和用户进行交互时被调用,此时activity位于的活动栈顶部。
2、paused状态:
运行状态到暂停状态所触发的函数及顺序为:onresume() -> onpuased()
暂停状态恢复至运行状态所触发的函数及顺序为:onpuased() -> onresume()。
注意:
2.1:onpuased()是当一个activity失去系统焦点后将会被调用,包括见面被部分遮挡,以及设备转入休眠状态等等。一般地在此期间对一些未保存的数据进行持久化并停 止其他需要耗费cpu的操作,同时不可进行耗时操作,否则会阻塞系统ui线程。
2.2:一个处于暂停状态的activity只有在系统极度缺乏内存资源的情况下才会被系统强制结束。
3、stopped状态:
暂停状态到停止状态所触发的函数及顺序为:onpuased() -> on stop()。
停止状态恢复至运行状态所触发的函数及顺序为:on stop() -> onrestart() -> on start() -> onresume()。
注意:
3.1:on stop()是当一个activity变为不可见时将会被调用,此时可能是由于该activity要被注销或新的activity完全遮挡了该activity。在此期间一般可以进行取消注册 广播等操作,因此用户不可见。
3.2:onrestart()是当一个activity从停止状态恢复至运行状态时将会被优先调用。
4、killed状态:
停止状态到死亡状态分为两种情况:(1)由用户操作导致,则执行:on stop() -> ondestroy()。
(2)由系统自动强制执行,则该activity被强行结束。
注意:
4.1:ondestroy()是当一个activity正在被系统finished期间被调用的。
第二:掌握activity的生命周期及各个阶段触发的事件名称和触发次数
activity一共有七个生命周期函数,分别为oncreate(),onrestart(),on start(),onreusme(),onpause(),on stop(),ondestory()。
1:oncreate()
当acitivity第一次被创建时触发,一般在这里要做的事情包括创建视图(setcontentview())、向视图填充必要的数据等等。
2:onrestart()
如果activity之前被stop过,那么下一次onstart()方法之前会先触发这个方法,当处于停止状态的活动需要再次展现给用户的时候,触发该方法。
3:onstart()
只要activity从不可见变成可见,就会触发到这个方法,但被alertdialog遮挡/显示的情况不算在内。
4:onresume()
当activity来到最上层的时候,也就是开始与用户直接交互时,触发这个方法。例如本来activity被一个alertdialog遮挡,当这个alertdialog消失时,onresume()方法就被触发。
5:onpause()
同onresume()的触发条件刚好相反,如果activity本来在最上层,当它要让出最上层的位置时会触发这个方法。
onpause()和onresume()是被触发最频繁的两个方法,所以在这里不应该执行过于消耗资源的方法。
6: onstop ()
当一个活动不再需要展示给用户的时候,触发该方法。如果内存紧张,系统会直接结束这个活动,而不会触发 onstop 方法。
所以保存状态信息是应该在onpause时做,而不是onstop时做。活动如果没有在前台运行,都将被停止或者linux管理进程为了给新的活动预留足够的存储空间而随时结束这些活动。因此对于开发者来说,在设计应用程序的时候,必须时刻牢记这一原则。在一些情况下,onpause方法或许是活动触发的最后的方法,因此开发者需要在这个时候保存需要保存的信息。
7: ondestroy ()
当活动销毁的时候,触发该方法。和onstop 方法一样,如果内存紧张,系统会直接结束这个活动而不会触发该方法。
接下来我们用代码来实现具体的方法触发:
创建一个android项目,在mainactivity中进行编辑
public class mainactivity extends activity { // oncreate系统自动初始化 @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); log.i("--mainactivity--","--------oncreate- 系统自动初始化---------"); } //从stop转为激活状态时执行 @override protected void onrestart() { super.onrestart(); log.i("--mainactivity--", "------onrestart--stop转为激活状态时执行----"); } //activity开始加载事件时执行(新创建时,或者重新启动的时候执行!) @override protected void onstart() { super.onstart(); log.i("--mainactivity--", "--------onstart---开始加载事件时执行-----"); } //activity恢复到激活状态时执行(任何一次进入激活状态都将执行) @override protected void onresume() { super.onresume(); log.i("--mainactivity--", "----------onresume-恢复到激活状态时执行-------------"); } //activity 被覆盖的时候执行 @override protected void onstop() { super.onstop(); log.i("--mainactivity--", "-------onstop ----被覆盖的时候执行-----------"); } //activity 退出或者被回收时执行,仅执行一次 @override protected void ondestroy() { super.ondestroy(); log.i("--mainactivity--","---------ondestroy---退出或者被回收时执行,仅执行一次--------------"); } }
当我们启动部署程序的时候,通过logcat 日志来查看信息
以上就是关于掌握activity的生命周期及各个阶段触发的事件名称和触发次数
第三:掌握activity中如何在各个窗体之间传值
如上我们知道了activity是一个窗体的页面显示,既然是页面显示,那么我们就需要进行显示数据与读取数据,那么问题来了,activity中如何在各个窗体之间进行传值。
这里引入一个关键字: intent:在android中,intent对象负责各个activity窗口之间的切换,同时他更担负起数据传输重任。
接下来我们用代码来具体实现分析(采用工具eclipse):
第一:首先我们创建一个名为activityvalue 的android项目 并在src 目录下分别创建名为:secondactivity java普通类 ,second_oneactivity java普通类 分别继承activity
在目录layout 中创建分别跟secondactivity ,second_oneactivity 相对应的布局xml文件
名为:activity_second_one.xml
名为:activity_second.xml
接下来我们在secondactivity.java 文件中进行编辑:
package com.example.activityvalue; import java.util.arraylist; import com.example.activitylife.r; import com.example.activityvalue.second_oneactivity; import android.app.activity; import android.content.intent; import android.os.bundle; import android.view.view; public class secondactivity extends activity{ @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); //声明activity setcontentview(r.layout.activity_second); } //传递一个普通值到一个窗体 public void mytestone(view view){ system.out.println("=================传递一个普通值到一个窗体====================="); intent intent = new intent(this,second_oneactivity.class); //窗体传值 intent.putextra("stuname","习大大"); intent.putextra("stuage",20); intent.putextra("ismerry",false); //设置数组 intent.putextra("stuhobby",new string[]{"篮球","羽毛球","足球"}); //设置集合数值 arraylist<string> list = new arraylist<string>(); list.add("北京"); list.add("广东"); list.add("美国"); //设置数值到intent 中 intent.putstringarraylistextra("stucitys",list); //开启activity startactivity(intent); } }
我们先在secondactivity 文件中部署好我们需要取出的数据 不同的类型数据m,由上文可知我们是通过intent 来进行传值
在second_oneactivity 进行编辑:
package com.example.activiyvalue; import java.lang.reflect.array; import java.util.arraylist; import java.util.arrays; import android.app.activity; import android.content.intent; import android.os.bundle; import android.widget.textview; public class second_oneactivity extends activity{ private textview showtext; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); //声明一个布局文件 setcontentview(r.layout.activity_second_one); //从intent 中取出传递过来的数据 intent intent = getintent(); //取出普通数据 string name = intent.getstringextra("stuname"); int age = intent.getintextra("stuage", 0); boolean ismerry = intent.getbooleanextra("ismerry",false); //取出数组数据 string[] hobbys = intent.getstringarrayextra("stuhobby"); string hobby = arrays.tostring(hobbys); //取出arraylist 集合数据 arraylist<string> citys =intent.getstringarraylistextra("stucitys"); string city = arrays.tostring(citys.toarray()); //声明activity showtext = (textview) findviewbyid(r.id.showtext); //在activity 中动态添加文本内容 string str = "姓名:"+name+",年龄:"+age+"\n"+ "婚否:"+ismerry+"\n"+ "爱好:"+hobby+"\n"+ "城市:"+city; showtext.settext(str); }
如果在第21 行 声明一个布局文件 报错时,则说明r 文件中 没有自动生成句柄 我们可以这样做
在项目右击重新加载项目便可:
接下来我们要在项目目录下的androidmainifest.xml 中进行声明activity 类文件
在声明的前提我们先进行设置好string参数
接下来在androidmainifest.xml 开始声明
接下来要回到mainactivity.java 定义一个方法 用来转跳activity
//============================打开一个窗体传值的案例============================== public void setvaluesmydemo(view view){ intent intent = new intent(this,secondactivityclass); //创建一个activity对象 //开始激活activity状态为start startactivity(intent); }
在activity_mainxml 布局文件中定义一个button 按钮
<button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="activity窗体传值案例" android:onclick="setvaluesmydemo" />
按钮绑定一个方法对应的是mainactivity.java 中的 setvaluesmydemo 方法
setvaluesmydemo 方法中调用 下一个activity 也就是secondactivity.java 对应的布局文件
那么我们就要在secondactivity.java 对应的布局文件activity_second.xml 中添加一个button
<button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="通过intent传递普通数据" android:onclick="mytestone"/>
activity_second.xml 中点击事件绑定的方法是secondactivity.java 文件中对应的mytestone方法:
在mytestone方法中 调用了下一个activity 也就是second_oneactivity.java 我们在这个文件中进行读取数据 在secondactivity.java文件中进行设置数值
接下来见证奇迹的时刻:我们运行我们的程序,打开我们的模拟器或者真机部署文件
点击窗体中的button 进入secondactivity的布局文件了 (此时就进行了页面的跳转)
在secondactivity页面我们是进行了设置数值 因此 当再次点击的时候我们在second_oneactivity 的布局文件就要进行读取数据
点击 显示跳转如下:
总结: 由上图案例可知,activity与activity 之间的跳转 跟 activity与activity 之间的传值 是通过上一个activity对下一个activity的调用,其中intent 对象 起到的方法很重要,起着跳转跟传值的任务!
第三: 掌握activity窗体状态保存问题
在这里如何保存当前的窗体状态我们通过代码来实现:
在我们上面的案例基础上,到mainactivity.java 文件中 重写activity 的两个方法:
onrestoreinstancestate(bundle savedinstancestate)
//========================窗体状态保存与恢复==================================== @override protected void onrestoreinstancestate(bundle savedinstancestate) { super.onrestoreinstancestate(savedinstancestate); //恢复状态 if(savedinstancestate!=null){ string msg = savedinstancestate.getstring("message"); //设置这个数据到需要的地方 toast.maketext(this, "以前的消息:"+msg, 50000).show(); } }
onsaveinstancestate(bundle outstate)
//========================保存的状态==================================== @override protected void onsaveinstancestate(bundle outstate) { // todo auto-generated method stub super.onsaveinstancestate(outstate); //保存数据 outstate.putstring("message", "hello!"); toast.maketext(this, "状态已经保存!", 3000).show(); }
完毕之后,我们开始运行程序最终结果如下:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。