今天开始学进程间的通信了
一、进程是什么
进程是是系统进行资源分配和调度的基本单位,线程是进程内相对独立的、可调度的执行单位,是分派cpu的基本单位。进程是线程的容器,即一个进程可包含多个线程。
单进程间的通信方式:
-----1. Intent-------实现方式:putExtra---------------特点:适合轻量级数据
-----2. SharePreference--实现方式:putInt、putString等----------特点:轻量、使用简单
-----3. 静态变量------实现方式:public static修饰-----------特点:全局可访问
-----4. 单例模式------实现方式:getInstance()获取对象,对象.的方式--特点:唯一对象
-----5. 文件--------实现方式:read、write-------------特点:持久化
-----6. 数据库-------实现方式:sql-----------------特点:轻量级、持久化
二、进程间通信
以上单进程通信方式都是不能进行进程间通信的,Intent的putExtras应该属于进程间通信方式,因为它绑定的数据都是实现了Parcelable接口的,可序列化的(理解的不够深不知道对不对)。
那么序列化是什么呢?序列化即将数据结构或对象转换成二进制串的过程。(没序列化时,对象保存在内存的堆中,序列化后把对象的状态(修饰符、数据结构不包括方法),保存在硬盘文件中),读取数据时进行反序列化,将在序列化过程中生成的二进制串转换成数据结构或对象。
如何实现序列化?可通过实现Serializable接口和实现Parcelable接口来进行。
Serializable接口:是java的序列化接口,它没有方法和字段,只是一个标记接口。
实现方式:新建一个实现了Serializable接口的类对象customer,创建一个设置了文件名和路径的ObjectOutputStream对象,再通过ObjectOutputStream对象.writeObject(customer)将序列化后的二进制数据存放进设置的路径中。反序列化的过程:创建一个设置了文件名和路径的ObjectIutputStream对象,新建实现了Serializable接口的Customer类的对象,使用ObjectIutputStream对象.readObject()获取数据并转换为customer对象,然后就可以输出信息啦,最后不要忘记关闭流对象哦。
如果有不想序列化的变量,可以使用static和transient修饰变量,这样变量就不会被序列化了。
部分代码:
序列化
Customer customer = new Customer();
customer.setAge(30);
customer.setName("lisi");
String path = getExternalCacheDir().getAbsolutePath(); //获取外部存储路径
File file = new File(path,"customer.txt"); //存储数据的文件的文件名
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file)); //获得ObjectOutputStream 对象
outputStream.writeObject(customer); //序列化并存放于文件中
outputStream.close(); //关闭流对象
反序列化
String path = getExternalCacheDir().getAbsolutePath(); //获取路径
File file = new File(path,"customer.txt"); //需要读取的文件名
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); //获取ObjectInputStream对象
Customer customer = (Customer) ois.readObject(); //反序列化转换
Log.d(TAG,"customer age = " + customer.getAge() + "customer name = " + customer.getName()); //输出信息
ois.close(); //关闭流对象
Serializable序列化也可以用bundle.putSerializable(“customer”,customer)打包后通过Intent发送,就不需要使用I/O流了
Parcelable接口是android的序列化接口,通过writeToParcek(Parcel dest,int flags)将数据写入Parcel实现序列化和通过createFromParcek(Parcel source)从Parcel中取出数据实现反序列化。
实现方式:新建一个实现了Parcelable接口的Person类,重写方法,在方法中进行读写,然后在Activity中用bundle.putParcelable(“person”,person)打包后通过Intent发送,在另一个Activity中接受intent,获取bundle,bundle.getParcelable(“person”)获取person对象就可以输出数据了。
部分代码:
person重写的方法
protected Person(Parcel in) {
name = in.readString(); //通过Parcel.read读取数据
age = in.readInt();
sex = in.readString();
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person createFromParcel(Parcel in) { //反序列化,从parcel容器中读取传递数据,封装为peson对象
return new Person(in);
}
@Override
public Person[] newArray(int size) { //返回一个类型为T,大小为size的数组
return new Person[size];
}
};
@Override
public void writeToParcel(Parcel dest, int flags) { //序列化
dest.writeString(name); //通过parcel.write写入到Parcel中
dest.writeInt(age);
dest.writeString(sex);
}
Activity中打包发送Intent
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
Bundle bundle = new Bundle(); //Bundle实现了Parcelable接口
Person person = new Person(); //创建实现Parcelable接口的类的对象
person.setSex("female");
person.setName("xiaosan");
person.setAge(21);
bundle.putParcelable("person",person); //Bundle存放实现Parcelable接口的类的对象
intent.putExtras(bundle); //将bundle放入intent中
startActivity(intent);
在SecondActivity中获取信息,在Manifest给SecondActivity设置了android:process=“com.example.multiprocess.second”,两个Activity属于不同进程
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
Person person = bundle.getParcelable("person"); //获取Person对象
Log.d(TAG," personAge:" + person.getAge() //输出信息
+ " personSex:" + person.getSex());
}
两种序列化方式就这样了,还有优缺点及应用场景
---序列化方式-----优点 ------缺点---------应用场景
--Serializable接口----代码少----开销大,速度慢----网络通信、内存序列化
--Parcelable接口 ---- 速度快-----代码多--------进程间通信