1、基本概念
IPC是Inter-Process Communication的缩写,表示进程间通信或跨进程通信。
进程是一个执行单元,一个程序或一个应用,系统会为每个进程分配独立的内存空间。在进程的执行过程中,很有可能需要与别的进程进行通信,比如说我们在淘宝付款时,淘宝就需要调用支付宝,并接收支付宝返回的付款成功与否的消息。因此,我们必须要学会如何进行进程间通信。
2、怎样开启多进程
Android开启多进程的方式很简单,就是在manifest文件中给activity、service等设置process属性,下面我们用实例来说明如何开启多线程。我们定义三个Activity和一个Service,从FirstActivity跳转到SecondActivity,再跳转到ThirdActivity,然后开启MyService
//3个xml文件
?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="BUTTON1" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="BUTTON2"/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button_3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="BUTTON3"/>
</LinearLayout>
//3个Activity
public class FirstActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
Button button1=(Button)findViewById(R.id.button_1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent);
}
});
}
}
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Button button2 = (Button)findViewById(R.id.button_2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(SecondActivity.this,ThirdActivity.class);
startActivity(intent);
}
});
}
}
public class ThirdActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_third);
Button button3 = (Button) findViewById(R.id.button_3);
button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(ThirdActivity.this, MyService.class);
startService(intent);
}
});
}
}
//MyService
public class MyService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
//Manifest文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.activitytest">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="ActivityText"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".FirstActivity"
android:launchMode="singleTop"
android:label="This is FirstActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SecondActivity"
android:process="com.example.activitytest.activity">
</activity>
<activity
android:name=".ThirdActivity"
android:process=":activity">
</activity>
<service android:name=".MyService"
android:process="com.example.myservice"/>
</application>
</manifest>
我们没有给FirstActivity制定process属性,给SecondActivity制定了process属性为“com.example.activitytest.activity”,给ThirdActivity设置的process属性为“activity”,给myService设置的process属性为“com.example.myservice”。
在运行之前我们需要借助Android drvice monitor来查看运行的线程。Android studio工具栏tools --> Android -->android device monitor
打开之后的界面是这样的,左侧选择我们已经连接好的模拟器或真机,就可以看到已经运行的进程
接下来我们边操作边查看device monitor的进程
打开程序之后我们会发现多了一个以包名“com.example.activitytest”为进程名的进程,很明显,我们的FirstActivity所在的进程名就是包名,说明进程名默认为包名
接下来我么点击button1,跳转到SecondActivity,这时增加了我们为SecondActivity指定的进程“com.example.activitytest.activity”
然后我们再点击button2,跳转到ThirdActivity。这是新增了一个“com.example.activitytest:activity”的进程,说明以:开头的进程,进程名前面会加上包名,实际上,以:开头的进程,是当前进程的私有进程
然后我们点击button3,开启myService。按照预期出现了我们为MyService指定的进程“com.example.myservice”
这样我们就开启了4个进程
3、序列化接口
数据要在进程间传输,必须要能够进行序列化和反序列化,Android中有两个序列化接口Serialzable和Parcelable
1)Serialzable是沿用了java中的序列化接口,使用起来非常简单,只需要实现Serializable即可
public class People implements Serializable{
private String name;
public People(){}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
}
2)Parcelable使用起来相对比较麻烦
public class People implements Parcelable{
private String name;
public People(String name){
this.name = name;
}
protected People(Parcel in) {
name = in.readString();
}
public static final Creator<People> CREATOR = new Creator<People>() {
@Override
public People createFromParcel(Parcel in) {
return new People(in);
}
@Override
public People[] newArray(int size) {
return new People[size];
}
};
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
}
}
3)区别
为什么已经有Serialzable了,Android工程师还要搞出来一个使用起来那么麻烦的Parcelable,肯定是因为Parcelable肯定是有不可替代的优势,那是什么优势呢?
因为Serialzable是Java的序列化接口,使用起来需要大量的I/O操作,开销很大;而Parcelable更适合Android平台,使用起来效率比Serialzable高很多
好了,有了这些基础,我们就可以学习Android进程间通信了
4、进程间通信的方式
Android实现进程间通信的6种方式分别是 Bundle , 文件共享 , Messenger , AIDL ,ContentProvider , Socket
这六种方式我会分别在接下来的六篇博客中手把手带着你实现
下一篇 Bundle实现进程间通信
特别感谢《Android 开发艺术探索》