全面解析Android应用开发中Activity类的用法
activity类处于android.app包中,继承体系如下:
1.java.lang.object
2.android.content.context
3.android.app.applicationcontext
4.android.app.activity
activity是单独的,用于处理用户操作。几乎所有的activity都要和用户打交道,所以activity类创建了一个窗口,开发人员可以通过setcontentview(view)接口把ui放到activity创建的窗口上,当activity指向全屏窗口时,也可以用其他方式实现:作为漂浮窗口(通过windowisfloating的主题集合),或者嵌入到其他的activity(使用activitygroup)。大部分的activity子类都需要实现以下两个接口:
oncreate(bundle)接口是初始化activity的地方. 在这儿通常可以调用setcontentview(int)设置在资源文件中定义的ui, 使用findviewbyid(int) 可以获得ui中定义的窗口.
onpause()接口是使用者准备离开activity的地方,在这儿,任何的修改都应该被提交(通常用于contentprovider保存数据).
为了能够使用context.startactivity(),所有的activity类都必须在androidmanifest.xml文件中定义有相关的“activity”项。
activity类是android 应用生命周期的重要部分。下面我们具体来总结一下activity的各个要点:
一、activity的生命周期
二、activity之间传递数据
1. 通过intent传递数据
通过intent.putextra方法可以将简单数据类型或可序列化对象保存在intent对象中,然后在另一个activity中使用getint、getstring等方法获得这些数据。示例代码如下:
intent intent =new intent(currentactivity.this,otheractivity.class); // 创建一个带“收件人地址”的 email bundle bundle =new bundle();// 创建 email 内容 bundle.putboolean("boolean_key", true);// 编写内容 bundle.putstring("string_key", "string_value"); intent.putextra("key", bundle);// 封装 email startactivity(intent);// 启动新的 activity
下面是获取数据:
intent intent =getintent();// 收取 email bundle bundle =intent.getbundleextra("key");// 打开 email bundle.getboolean("boolean_key");// 读取内容 bundle.getstring("string_key");
不过使用bundle传递数据稍显麻烦,如果你只需要传递一种类型的值可以这样:
intent intent =new intent(ex06.this,otheractivity.class); intent.putextra("boolean_key", true); intent.putextra("string_key", "string_value"); startactivity(intent);
获取数据:
intent intent=getintent(); intent.getbooleanextra("boolean_key",false); intent.getstringextra("string_key");
2. 通过静态变量传递数据
适用于不可序列化的且简单的对象,不过不推荐使用静态代码块
public class mainactivity extends activity { private button btn; @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); btn = (button)findviewbyid(r.id.btopenotheractivity); btn.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { //定义一个意图 intent intent = new intent(mainactivity.this,otheractivity.class); //改变otheractivity的三个静态变量的值 otheractivity.name = "wulianghuan"; otheractivity.age = "22"; otheractivity.address = "上海闵行"; startactivity(intent); } }); } } public class otheractivity extends activity { public static string name; public static string age; public static string address; private textview text_name; private textview text_age; private textview text_address; @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.other); text_name = (textview) findviewbyid(r.id.name); text_age = (textview) findviewbyid(r.id.age); text_address = (textview) findviewbyid(r.id.address); //设置文本框的数据 text_name.settext("姓名:"+name); text_age.settext("年龄:"+age); text_address.settext("地址:"+address); } }
3.通过全局对象传递数据
如果想使某些数据长时间驻留内存,以便程序随时调用,建议采用全局对象。application全局类不需要定义静态变量只要定义普通成员变量即可,但全局类中必须有一个无参构造方法,编写完application类后,还需要在<application>标签中制定全局类名,否则系统不会自动创建全局对象。
public class mainapplication extends application { private string username; public string getusername() { return username; } public void setusername(string username) { this.username = username; } } public class mainactivity extends activity { private mainapplication application; public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); application = (mainapplication) getapplication(); application.setusername("sunzn"); } public void open(view view) { intent intent = new intent(this, otheractivity.class); startactivity(intent); } } public class otheractivity extends activity { private textview tv_data; private mainapplication application; private string username; protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_other); application = (mainapplication) getapplication(); username = application.getusername(); tv_data = (textview) findviewbyid(r.id.tv_data); tv_data.settext("从上一个 activity 中获取到的数据为:" + username); } }
三、从activity返回数据
要从activity返回数据,需要使用startactivityforresult方法来显示activity。
从activity1跳转到activity2:
intent intent = new intent(); intent = intent.setclass(activityintent.this, anotheractivity.class); bundle bundle = new bundle(); bundle.putstring("string", et_string.gettext().tostring()); intent.putextras(bundle); startactivityforresult(intent,0); //只有这里不同
从activity2返回数据到aactivity1:
intent intent = new intent(); intent = intent.setclass(anotheractivity.this, activityintent.class); bundle bundle = new bundle(); bundle.putint("result", "activity2的处理结果"); intent.putextras(bundle); anotheractivity.this.setresult(result_ok, intent); //result_ok是返回状态码 anotheractivity.this.finish();
在activity1中重写onactivityresault方法,接受数据:
protected void onactivityresult(int requestcode, int resultcode, intent data) { super.onactivityresult(requestcode, resultcode, data); switch(resultcode) { //根据状态码,处理返回结果 case result_ok: bundle bundle =data.getextras(); //获取intent里面的bundle对象 string result = bundle.getint("result"); break; default: break; } }
四、activity的四种创建模式
我们在开发项目的过程中,会涉及到该应用中多个activity组件之间的跳转,或者夹带其它应用的可复用的activity。例如我们可能希望跳转到原来某个activity实例,而不是产生大量重复的 activity。这样就需要我们为 activity 配置特定的加载模式,而不是使用默认的加载模式。设置启动模式的位置在 manifest.xml 文件中 activity的android:launchmode 属性
1.standard 模式
这是默认模式,无需设置,每次激活activity时都会创建activity实例,并放入任务栈中。相当于入栈,按back键返回到前一个activity相当于退栈。
2.singletop 模式
如果在任务的栈顶正好存在该activity的实例,就重用该实例( 会调用实例的 onnewintent()),否则就会创建新的实例并放入栈顶,即使栈中已经存在该activity的实例,只要不在栈顶,都会创建新的实例。可用来解决栈顶多个重复相同的activity的问题
3.singletask 模式
如果在栈中已经有该activity的实例,就重用该实例(会调用实例的 onnewintent() )。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移出栈。如果栈中不存在该实例,将会创建新的实例放入栈中。singletask 模式可以用来退出整个应用。将主activity设为singtask模式,然后在要退出的activity中转到主activity,然后重写主activity的onnewintent函数,并在函数中加上一句finish。
4.singleinstance 模式
在一个新栈中创建该activity的实例,并让多个应用共享该栈中的该activity实例。一旦该模式的activity实例已经存在于某个栈中,任何应用再激活该activity时都会重用该栈中的实例( 会调用实例的 onnewintent() )。其效果相当于多个应用共享一个应用,不管谁激活该 activity 都会进入同一个应用中。
五、activity现场保存状态
一般来说,调用onpause()和onstop()方法后的activity实例仍然存在于内存中,activity的所有信息和状态数据不会消失, 当activity重新回到前台之后, 所有的改变都会得到保留。但是当系统内存不足时, 调用onpause()和onstop()方法后的activity可能会被系统摧毁, 此时内存中就不会存有该activity的实例对象了. 如果之后这个activity重新回到前台, 之前所作的改变就会消失.可以在activity被杀掉之前调用保存每个实例的状态,开发者可以覆写onsaveinstancestate()方法. onsaveinstancestate()方法接受一个bundle类型的参数, 开发者可以将状态数据存储到这个bundle对象中,以保证该状态在oncreate(bundle)或者onrestoreinstancestate(bundle)(传入的bundle参数是由onsaveinstancestate封装好的)中恢复。这个方法在一个activity被杀死前调用,当该activity在将来某个时刻回来时可以恢复其先前状态。如果调用onsaveinstancestate()方法,调用将发生在onpause()或onstop()方法之前,而且它也不是生命周期的方法。
若向数据库中插入记录等,保存持久化数据的操作应该放在onpause()中. onsaveinstancestate()方法只适合保存瞬态数据, 比如ui控件的状态, 成员变量的值等.
public class mainactivity extends activity { private string temp; @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); // 从savedinstancestate中恢复数据, 如果没有数据需要恢复savedinstancestate为null if (savedinstancestate != null) { temp = savedinstancestate.getstring("temp"); system.out.println("oncreate: temp = " + temp); } } public void onrestoreinstancestate(bundle saveinstancestate) { super.onrestoreinstancestate( saveinstancestate); string temp = saveinstancestate.getstring("temp"); system.out.println("onresume: temp = " + temp); } // 将数据保存到outstate对象中, 该对象会在重建activity时传递给oncreate方法和onrestoreinstancestate方法 @override protected void onsaveinstancestate(bundle outstate) { super.onsaveinstancestate(outstate); outstate.putstring("temp", temp); }
六、一些关于activity的技巧
1.设置activity的方向
android:screenorientation="portrait">// 竖屏 , 值为 landscape 时为横屏
2.设置activity全屏
在oncreate方法中添加如下代码:
// 设置全屏模式 getwindow().setflags(windowmanager.layoutparams.flag_fullscreen, windowmanager.layoutparams.flag_fullscreen); // 去除标题栏 requestwindowfeature(window.feature_no_title);
改变窗口大小、位置、透明度
在oncreate方法中添加如下代码:
window w=getwindow(); w.setbackgrounddrawableresource(resourceid);//设置窗口背景 windowmanager.layoutparams layoutparams = w.getattributes(); layoutparams.height = 200; layoutparams.width= 200; layoutparams.gravity = gravity.top; layoutparams.x=50;//距离gravity属性的距离 layoutparams.y=50; layoutparams.alpha = 0.5;//0:完全透明,1:不透明 w.setattributes(layoutparams);
3.关闭所有窗口
intent intent = new intent(); intent.setclass(android123.this, cwj.class); intent.setflags(intent.flag_activity_clear_top); //注意本行的flag设置 startactivity(intent)
另一种方法:在调用退出方法中写上myapplication.getinstance().exit();
public class myapplication extends application { private list<activity> activitylist = new linkedlist<activity>(); private static myapplication instance; private myapplication() { } // 单例模式中获取唯一的myapplication实例 public static myapplication getinstance() { if (null == instance) { instance = new myapplication(); } return instance; } // 添加activity到容器中 public void addactivity(activity activity) { activitylist.add(activity); } // 遍历所有activity并finish /* * 在每一个activity中的oncreate方法里添加该activity到myapplication对象实例容器中 * * myapplication.getinstance().addactivity(this); * * 在需要结束所有activity的时候调用exit方法 * * myapplication.getinstance().exit(); */ public void exit() { for (activity activity : activitylist) { activity.finish(); } system.exit(0); }
推荐阅读
-
深入解析Android App开发中Context的用法
-
Android应用UI开发中Fragment的常见用法小结
-
Android应用开发中View绘制的一些优化点解析
-
Android应用开发中Fragment存储功能的基本用法
-
详解Android应用开发中Scroller类的屏幕滑动功能运用
-
简介Android应用中sharedPreferences类存储数据的用法
-
全面解析Android应用开发中Activity类的用法
-
深入解析Android App开发中Context的用法
-
Android应用UI开发中Fragment的常见用法小结
-
Android应用开发中Fragment存储功能的基本用法