引入:对于新手来说,不了解Activity的生命周期以及通信则非常容易产生这样一个问题:这段代码为什么跑起来了?这段代码为什么跑不了?
原因:Activity有自己的生命周期方法以及通信原理,然后通过系统的回调机制,互相调用。
主题:Activity的生命周期以及通信的详解
一:Activity的生命周期方法:
1.onCreat();
活动开始前系统调用:
2.onStart();
活动开始时系统调用:
3.onResume();
活动在进行时系统调用:
4.onRestart();
活动不在视野内但又不被摧毁时重新回到视野内系统调用:(即按下home键后然后重新点进来)
5.onPause();
活动暂定时调用,即活动在视野内但出现线程阻塞时调用,比如出现警告窗口时就会触发
6.onStop();
活动不在视线范围内但又不被摧毁时系统调用;
7.onDestroy()
活动被摧毁时系统调用(即按下back键)
=================================================
理论知识是枯燥的,自己动手实验才是最有趣的,下面直接撸码:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e(TAG, "onCreate: ");
}
@Override
protected void onStart() {
super.onStart();
Log.e(TAG, "onStart: ");
}
@Override
protected void onResume() {
super.onResume();
Log.e(TAG, "onResume: " );
}
@Override
protected void onRestart() {
super.onRestart();
Log.e(TAG, "onRestart: " );
}
@Override
protected void onPause() {
super.onPause();
Log.e(TAG, "onPause: " );
}
@Override
protected void onStop() {
super.onStop();
Log.e(TAG, "onStop: " );
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.e(TAG, "onDestroy: ");
}
}
首先:跑一下程序,即刚进入到活动的运行结果:
然后我们按下home键:
接着在页面没有被摧毁的状态下重新进入到页面:
最后我们按下back键:
系统的回调机制很奇妙对吧,当然你可以自己操作进行尝试,这将会更加有趣并且印象更深刻,测试代码就在上面,欢迎拿去使用
当然了解生命周期后你就可以利用生命周期进行各种功能的实现,比如但播放视频暂停时你要怎么做,当出现弹窗后客户页面被卡死时我们后台要如何去执行特定的操作等等,
二. Activity之间的通信方式------Intent意图跳转
由于Intent的隐式用法不常用,因此在这我只对Intent的显式用法进行详解
我们先讲活动之间的跳转,再讲数据的传递、
首先我们还是需要获取Intent对象,代码如下:
Intent intent = new Intent(MainActivity.this, MainActivity2.class);
startActivity(intent);
获取Intent参数解析:第一个参数是目前Activity的Context对象,这里传入自身就行了,第二个参数是要跳转到的Activity对象
第二行代码就是开启这个意图,该方法在Activity类中
我先加入一个Button来启动这个activity比较方便展示,代码如下
Button bt1 = (Button) findViewById(R.id.bt1);
bt1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Bundle bundle = new Bundle();
bundle.putString("name","秃头小郑");
bundle.putInt("age",20);
Intent intent = new Intent(MainActivity.this, MainActivity2.class);
intent.putExtra("name","秃头小郑")
.putExtra("age",20);
// .putExtras(bundle)
startActivity(intent);
}
});
按下跳转到第二个ACTIVITY按钮后 运行结果如下:


这样就成功跳转到第二个页面来了
那么问题来了,我们在第一个页面跳转的时候的数据怎么带过来呢?
这就需要用到我们的Intent的通信了
Intent通信方式(一):携带基础数据类型:
Intent对象可以使用putExtras()方法传递基本类型数据,因为方式差不多,所以我就简单地撸了几行,用法参数都差不多,第一个参数是名字(即Key),第二个参数是值(即Value),可以联想Map的映射去记忆。
下面开始撸码:这里也可以使用链式调用,不用讲究顺序
第一个activity中传递数据时:
intent.putExtra("name","秃头小郑")
.putExtra("age",20);
跳转到的activity接受到数据时:
Intent intent = getIntent();
String name = intent.getStringExtra("name");
int age = intent.getIntExtra("age",0);
Log.e("MainActivity2", "我是 "+ name + ", " + age + " 岁了。" );
上面获取age时传入的第二个参数是个当获取不到”age“时传回来的默认值,这里随便写个0就行
然后我们跑一下程序:
这样我们就接收到从该activity传回来的数据了
二. Intent传递Bundle类型:
Bundle类只是一个对数据进行包装的类,有很多的putXXXX方法,这里不详细讲解
第一个activity中的代码:
Bundle bundle = new Bundle();
bundle.putString("name","秃头小郑");
bundle.putInt("age",20);
intent.putExtras(bundle);
第二个activity的代码:
声明:在activity接收到的Bundle时会自动进行拆装
因此代码与第一个获取数据时是一模一样的
Intent intent = getIntent();
String name = intent.getStringExtra("name");
int age = intent.getIntExtra("age",0);
Log.e("MainActivity2", "我是 "+ name + ", " + age + " 岁了。" );
上面的用法只能传递基本数据类型,不能传递对象,那么再来讲下Intent的高阶用法,传递对象参数。
三.高阶用法之----传递Serialzable对象
intent里面有个方法去传递Serialzable对象:
操作如下:只需要传递的对象去实现Serialzable接口就可以传递了
代码如下:
public class Worker implements Serializable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
行了,现在可以开始传递了,
第一个activity:
Worker worker = new Worker();
worker.setName("秃头小郑");
worker.setAge(20);
intent.putExtra("worker",worker);
第二个activity:
Worker worker = (Worker) intent.getSerializableExtra("worker");
String name = worker.getName();
int age = worker.getAge();
Log.e("MainActivity2", "我是 "+ name + ", " + age + " 岁了。" );
声明一点,这里一定要强制转换类型,因为源码接收的不是泛型,不会自动转成相应的对象
跳转后运行结果:
三.Intent高阶用法之:传递Parcelable对象
这个用法相对比较复杂,底层有涉及到C语言指针问题,是个坑
用法:依旧是使用的对象类去实现Parcelable接口,但略有不同,因为重新了几个Parcelable需要用到的抽象方法,话不多说直接开撸:
public class Student implements Parcelable {
public Student(){}
public String name;
public int age;
//TODO 注意: 读的顺序要和写的顺序一直,否则会报错,因为写的操作的API是由C语言的指针写的,所以可能读取到的长度不一致
//从Parcel对象中获取相关的数据,该方法是在跳转到的活动里被调用,即跳转后的页面获取数据时调用
public Student(Parcel in) {
name = in.readString();
age = in.readInt();
}
//系统为了扩展一些功能用的,这里不理它
@Override
public int describeContents() {
return 0;
}
//从跳转前的活动写数据到Parcel的对象中,方便读的时候获取,读写顺序要一致,强调!!否则报错
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
//CREATOR一定要有,系统自动生成,不需要我们改写
public static final Creator<Student> CREATOR = new Creator<Student>() {
//创建Student对象 并且在Parcel构建好后传递给Student对象,这样成员数据就可以从Parcel中获取了
@Override
public Student createFromParcel(Parcel in) {
return new Student(in);
}
//辅助方法用不到,直接这么写就好
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
}
各种方法的用法我都写在注释里了,各位直接看代码就行。
现在终于可以开始使用了.
第一个活动:
Student student = new Student();
student.name = "秃头小郑";
student.age = 20;
第二个活动:
Student student = intent.getParcelableExtra("student");
String name = student.name;
int age = student.age;
Log.e("MainActivity2", "我是 "+ name + ", " + age + " 岁了。" );
这里与Serialzble对象的区别就是不用强制转成Student类,因为源码接收的是泛型。
跳转后运行结果:
到此Acitvity的生命周期以及通信的总结结束:希望能帮到想入门的开发人员哈,以身试坑,让各位少走弯路。
之后遇到更高级的用法会再一一分享。