前言:
Activity是Android四大组件之一,为用户提供与系统交互的界面,每一个应用都有一个或者多个Acticity。
Activity简单的介绍:
一个Activity是一个应用程序组件,提供一个屏幕,用户可以用来交互为了完成某项任务,例如拨号、拍照、发送email、看地图。每一个activity被给予一个窗口,在上面可以绘制用户交互的画面。窗口通常充满屏幕,但也可以小于屏幕而浮于其它窗口之上。一个用户交互界面对应一个activity,相当于是界面的容器setContentView(),activity 是Context的子类,同时实现了window.callback接口(里面方法如dispatchtouchevent可以分发事件)和keyevent.callback等, 可以处理与窗体用户交互的事件。
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks2,
Window.OnWindowDismissedCallback {}
创建activity
- 创建class类继承Activity
- 创建布局文件,作为Activity的显示内容
3. 在清单文件中注册Activity
平常需要注意的一些问题:
- 需要在清单文件中为其配置一个activity标签,声明你的activity在manifest文件为了它可以被系统访问。否则如果系统找不到,在显示时会直接产生ActivityNotFoundException。要声明你的activity,打开manifest文件,添加一个activity元素作为application元素的子元素。
- Activity 在调用的时候才会实例化,如果manifest没有声明这个activity,不使用则不会报错。
- 如果Activity所在的包跟应用包名同名,那么可以省略不写。而用.xxxActivity来代替。
标签中如果带有这个子节点,则会在系统中创建一个快捷图标
<intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter>
- 声明入口activity,就会生成快捷图标,可以声明多个入口activity,会产生多个Activity对应的快捷图标。
activity的名称label、图标icon可以和应用程序application节点的名称、图标不相同,但默认使用application节点下的属性。
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
activity的跳转
Activity的跳转需要创建Intent对象,通过设置intent对象的参数指定要跳转的activity。通过设置Activity的包名和类名实现跳转,称为显式意图。
通过指定动作实现跳转,称为隐式意图。
1.显示意图
跳转至同一项目下的另一个Activity,直接指定该Activity的字节码即可
Intent intent = new Intent();
intent.setClass(this, SecondActivity.class);
startActivity(intent);
跳转至其他应用中的Activity,需要指定该应用的包名和该Activity的类名
Intent intent = new Intent();//启动系统自带的拨号器应用
intent.setClassName("com.android.dialer","com.android.dialer.DialtactsActivity");
startActivity(intent);
2.隐式意图
隐式意图跳转至指定Activity
Intent intent = new Intent();//启动系统自带的拨号器应用
intent.setAction(Intent.ACTION_DIAL);
startActivity(intent);
- 要让一个Activity可以被隐式启动,需要在清单文件的activity节点中设置intent-filter子节点
- action 指定动作(可以自定义,可以使用系统自带的,可以使任意字符串,但一般写全类名)
- data 指定数据(操作什么内容,包括URI和数据类型)
category 类别 (默认类别)
<intent-filter >
<action android:name="com.chenqiao.second"/>
<data android:scheme="chenqiao" android:mimeType="aa/bb"/>
<category android:name="android.intent.category.DEFAULT"/></intent-filter>
隐式意图的属性设置
1.创建意图对象 意图就是我要完成一件事
Intent intent = new Intent();//[2] 设置跳转的动作
intent.setAction("com.chenqiao.testactivity");//[3] 设置category
intent.addCategory("android.intent.category.DEFAULT");//[4]设置数据// intent.setData(Uri.parse("chenqiao:"+110));//[5]设置数据类型//intent.setType("aa/bb");//[6]注意 如果setdata 方法和 settype 方法一起使用的时候 应该使用下//面这个方法
intent.setDataAndType(Uri.parse("chenqiao:"+110), "aa/bb");//[4]开启Activity
startActivity(intent);
要启动的那个activity的意图过滤器
<intent-filter><action android:name="com.itheima.testactivity" /><category android:name="android.intent.category.DEFAULT" /><data android:mimeType="aa/bb" android:scheme="chenqiao" /></intent-filter>
- 隐式意图启动Activity,需要为intent设置以上三个属性,且值必须与该Activity在清单文件中对三个属性的定义匹配。intent-filter节点及其子节点都可以同时定义多个,隐式启动时只需与任意一个匹配即可。在启动效率上,隐式远低于显示。
如果系统中存在多个Activity的intent-filter同时与你的intent匹配,那么系统会显示一个对话框,列出所有匹配的Activity,由用户选择启动哪一个。显式意图一般用于启动同一应用中的Activity。隐式意图一般用于启动不同应用中的Activity,因为不能拿到另一个应用的activity类名,不能显示启动。
activity跳转时的数据传递
Activity之间的数据传递,常见的有4中,Intent传递简单数据,Bundle传递数据包,传递值对象,获取Activity的返回参数。
1.intent传递简单数据
Intent intent = new Intent(this, SecondActivity.class);
intent.putExtra("maleName", maleName);
intent.putExtra("femaleName", femaleName);
startActivity(intent);
在目标activity中取出数据‘’
Intent intent = getIntent();String maleName = intent.getStringExtra("maleName");String femaleName = intent.getStringExtra("femaleName");
2.bundle传递数据包
Mainivity:
Intent intent = new Intent(MainActivity.this,OtherActivity.class);
Bundle bundle = new Bundle();
bundle.putString("name","MirGao");
bundle.putString("age","24");
intent.putExtras(bundle);
startActivity(intent);
Otheractivty:
Intent intent = getIntent();
Bundle b = intent.getExtras();
tv.setText(b.getString("name") + " " + b.getString("age"));
3.传递值对象
所谓的值对象,就是我们通常在项目中自定义的,有数据类型的javabean。
那我们就先自定义一个数据类型。
public class UserBean implements Serializable{
private String name;
private String age;
public UserBean(String name, String age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(String age) {
this.age = age;
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
}
然后实现序列化
在MainActivity中直接进行自定义对象的传递,并赋予两个参数:
Intent intent = new Intent(MainActivity.this,OtherActivity.class);
intent.putExtra("UserBean",new UserBean("MirGao","24"));
startActivity(intent);
Otheractivity中获取值对象数据:
UserBean userBean ;
userBean = (UserBean) getIntent().getSerializableExtra("UserBean");
tv.setText(userBean.getName() + " " + userBean.getAge());
使用UserBean对象获取序列化后的对象并进行强制转换,并通过获取的对象,进行操作。使用序列化很简单,方便的可以进行复杂,大量数据的传递。但是,Serializable与Parcelable相比而言 效率比较低 ,所以Android平台又给我们提供了Parcelable,他是一个专门针对移动工具上数据序列化的接口
public class UserBean implements Parcelable{
private String name;
private String age;
public UserBean(String name, String age) {
this.name = name;
this.age = age;
}
protected UserBean(Parcel in) {
name = in.readString();
age = in.readString();
}
public void setName(String name) {
this.name = name;
}
public void setAge(String age) {
this.age = age;
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(getName());
dest.writeString(getAge());
}
public static final Creator<UserBean> CREATOR = new Creator<UserBean>() {
@Override
public UserBean createFromParcel(Parcel in) {
return new UserBean(in.readString(),in.readString());
}
@Override
public UserBean[] newArray(int size) {
return new UserBean[size];
}
};
}
实现了Parcelable接口,并且实现了3个方法
总结:Serializable和Parcelable都是序列化接口,因为Serializable简单,方便,Android系统对他有自动完成序列化的操作,所以速度是比较慢的。而Parcelable中都是手动去添加数据类型,读取数据,Android系统并没有给我们提供序列化机制,所以Parcelable的数据是相对复杂的,但是速度是比较快的。所以在使用时,注意优缺点选择。
4.启动Activity并获取返回值
从A界面打开B界面, B界面关闭的时候,返回一个数据给A界面
1.开启activity并且获取返回值
//第一个参数为请求码,即调用startActivityForResult()传递过去的值//第二个参数为结果码,可以根据业务需求自己编号,结果码用于标识返回数据来自哪个新Activity
startActivityForResult(intent, 0);
2.在新开启的界面里面实现设置数据的逻辑
Intent data = new Intent();
data.putExtra("phone", phone);//设置一个结果数据,数据会返回给调用者
setResult(0, data);
finish();//关闭掉当前的activity,才会返回数据
3.在开启者activity里面实现方法
//通过data获取返回的数据
onActivityResult(int requestCode, int resultCode, Intent data)
根据请求码和结果码确定业务逻辑
请求码:用来区分数据来自于哪一个Activity
结果码:用来区分,返回的数据时属于什么类型
5.activity的生命周期
void onCreate():Activity已经被创建完毕,当Activity第一次启动的时候,触发该方法,可以在此时完成Activity的初始化工作。onCreate 方法有一个参数,该参数可以为空( null ),也可以是之前调用onSaveInstanceState()方法保存的状态信息。
void onStart():该方法的触发表示所属Activity将被展现给用户。Activity已经显示在屏幕,但没有得到焦点。
void onResume():Activity得到焦点,可以与用户交互。
void onPause():Activity失去焦点,无法再与用户交互,但依然可见。当一个正在前台运行的Activity因为其他的Activity需要前台运行而转入后台运行的时候,触发该方法。这时候需要将Activity的状态持久化,比如正在编辑的数据库记录等。
void onStop():Activity不可见,进入后台。当一个Activity不再需要展示给用户的时候,触发该方法。如果内存紧张,系统会直接结束这个Activity,而不会触发onStop 方法。所以保存状态信息是应该在onPause 时做,而不是onStop 时做。Activity如果没有在前台运行,都将被停止或者Linux 管理进程为了给新的Activity预留足够的存储空间而随时结束这些Activity。因此对于开发者来说,在设计应用程序的时候,必须时刻牢记这一原则。在一些情况下,onPause 方法或许是Activity触发的最后的方法,因此开发者需要在这个时候保存需要保存的信息。
void onDestroy():Activity被销毁。当Activity销毁的时候,触发该方法。和onStop 方法一样,如果内存紧张,系统会直接结束这个Activity而不会触发该方法。
·onSaveInstanceState :系统调用该方法,允许Activity保存之前的状态,比如说在一串字符串中的光标所处的位置等。通常情况下,开发者不需要重写覆盖该方法,在默认的实现中,已经提供了自动保存Activity所涉及到的用户界面组件的所有状态信息。
void onRestart():当处于停止状态的Activity需要再次展现给用户的时候,触发该方法,即从不可见变成可见时会执行此方法
生命周期(entire lifetime)
onCreate-->onStart-->onResume-->onPause-->onStop-->onDestory
命周期(visible lifetime)
onStart-->onResume-->onPause-->onStop
前台生命周期(foreground lifetime)
onResume-->onPause
6.Activity的启动模式
standard标准启动模式
默认的启动模式,新启动的Activity放入返回栈栈顶,遵循先进后出原则,同一个Activity可以被实例化多次。
singleTop 单一顶部模式
如果任务栈的栈顶存在这个要开启的activity,不会重新的创建activity,而是复用已经存在的activity。保证栈顶如果存在,不会重复创建。
应用场景:浏览器的书签
singeTask 单一实例模式
当开启activity的时候,就去检查在任务栈里面是否有实例已经存在,如果有实例存在就复用这个已经存在的activity,并且把这个activity上面的所有的别的activity都清空,复用这个已经存在的activity。保证整个任务栈里面只有一个实例存在.
应用场景:浏览器的activity。从不同地方打开浏览器使用的都是同一个实例。
如果一个activity的创建需要占用大量的系统资源(cpu,内存)一般配置这个activity为singletask的启动模式。
singleInstance单一任务栈模式
singleInstance启动模式非常特殊, activity会运行在自己的任务栈里面,并且这个任务栈里面只有一个实例存在。如果你要保证一个activity在整个手机操作系统里面只有一个实例存在,使用singleInstance
应用场景: 电话拨打界面。
以上就是我所总结的,望大家借鉴!
//第一
//第一个参数为请求码,即调用startActivityForResult()传递过去的值//第二个参数为结果码,可以根据业务需求自己编号,结果码用于标识返回数据来自哪个新Activity
startActivityForResult(intent, 0);
个参数为请求码,即调用startActivityForResult()传递过去的值//第二个参数为结果码,可以根据业务需求自己编号,结果码用于标识返回数据来自哪个新Activity
startActivityForResult(intent, 0);
Inte
nt intent = getIntent();String maleName = intent.getStringExtra("maleName");String femaleName = intent.getStringExtra("femaleName");
Intent intent = getIntent();String maleName = intent.getStringExtra("maleName");String femaleName = intent.getStringExtra("femaleName");
Intent intent = getIntent();String maleName = intent.getStringExtra("maleName");String femaleName = intent.getStringExtra("femaleName");