一. 前言

1. 什么是进程?

  • 就是运行的一个程序。
  • 每个进程都有独立的代码和数据空间,进程间的切换会有较大的开销,一个进程包含1~n个线程。
  • 进程是资源分配的最小单位。
  • 一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。

2. 什么是多进程?

多进程是指操作系统同时运行多个进程。

3. 进程如何创建?

1
android:process

4. 进程的等级

  • 前台进程
  • 可见进程
  • 服务进程
  • 后台进程
  • 空进程

二. 多进程

1. 什么情况下使用多进程?

Android中一个进程的内存是有限的,当需要更多的内存时。

2. 使用多进程需要注意哪些地方?

多个进程可能会导致全局初始化操作多次执行。

1
2
3
4
5
6
7
8
9
10
11
public class MainApplication extends Application {

@Override
public void onCreate() {
super.onCreate();
//全局初始化操作

//多个进程会多次进入该方法,造成资源浪费
//可以通过判断进程来确定是否初始化
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="swu.xl.messenger">

<application

android:name=".MainApplication"

android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

三. 进程间的通信 IPC(inter process communication)

1. 为什么需要进程间的通信

进程间内存的不可见性,导致了内存不共享。

2.如何通信?

  • 系统实现
  • Messenger
  • AIDL:Android Interface definition language

3. Messenger方式

① 适用情况

多进程+单线程

② 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//处于另外一个进程的Service
public class MessengerService extends Service {
public static final String TAG = MessengerService.class.getSimpleName();

//创建Messenger
Messenger messenger = new Messenger(new CommunicationHandler());

//创建Handler
@SuppressLint("HandlerLeak")
class CommunicationHandler extends Handler{
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);

//处理消息
switch (msg.what){
case 0:
Log.d(TAG,msg.arg1+"---");
Toast.makeText(MessengerService.this, "数据:"+msg.arg1, Toast.LENGTH_SHORT).show();
break;
default:
throw new IllegalStateException("Unexpected value: " + msg.what);
}
}
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
return messenger.getBinder();
}
}

//注册
<service android:name=".MessengerService"
android:process="swu.xl.messenger.service"/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class MainActivity extends AppCompatActivity {
public static final String TAG = MessengerService.class.getSimpleName();

//全局化Messenger
private Messenger messenger;

//ServiceConnection
private ServiceConnection serviceConnection = new ServiceConnection() {

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
messenger = new Messenger(service);

Message message = Message.obtain();
message.what = 0;
message.arg1 = 10;
try {
messenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();

Toast.makeText(MainActivity.this, "远程异常", Toast.LENGTH_SHORT).show();
}
}

@Override
public void onServiceDisconnected(ComponentName name) {

}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

bindService(
new Intent(this,MessengerService.class),
serviceConnection,
Context.BIND_AUTO_CREATE
);
}
}

③ 进程图

④ 运行效果图

4. AIDL方式

① 适用情况

多进程+多线程

② 代码

1> 在模块名.src.main创建 aidl 文件夹,在该文件夹中创建AIDL文件,系统会自动帮我们自动创建一个包,如下图所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
// IMyAidlInterface.aidl
package swu.xl.aidl;

// Declare any non-default types here with import statements

interface IMyAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
}

2> 使用Build -> Make Project,让系统自动生成代码,生成代码的位置如下图所示:

3> 在aidl文件中,构建自己想要传递数据的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// IMyAidlInterface.aidl
package swu.xl.aidl;

// Declare any non-default types here with import statements

interface IMyAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);

//构造的传递数据的方法
String getName(String nickName);
}

此时,还需要 Build -> Make Project,因为添加了新的内容,所以需要重新生成代码。

4> 创建在新的进程的一个服务,和MainActivity进行通信。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class AIDLService extends Service {

IMyAidlInterface.Stub stub = new IMyAidlInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

}

@Override
public String getName(String nickName) throws RemoteException {
return nickName+"你好";
}
};


@Nullable
@Override
public IBinder onBind(Intent intent) {
return stub;
}
}
1
2
3
//注册
<service android:name=".AIDLService"
android:process=":aidl"/>

5> MainActivity中的调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class MainActivity extends AppCompatActivity {

private IMyAidlInterface iMyAidlInterface;

private ServiceConnection serviceConnection = new ServiceConnection() {

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
}

@Override
public void onServiceDisconnected(ComponentName name) {

}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

bindService(new Intent(this,AIDLService.class), serviceConnection, Context.BIND_AUTO_CREATE);

findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

if (iMyAidlInterface != null){
try {
String test = iMyAidlInterface.getName("test");
Toast.makeText(MainActivity.this, "name:"+test, Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
});

}
}
1
2
3
//该方法在生成的 IMyAidlInterface.java 文件中。
//是该接口的内部类 Stub 的一个静态方法。
public static swu.xl.aidl.IMyAidlInterface asInterface(android.os.IBinder obj)

6> 进程图

7> 运行效果图

5. 源代码

MultiProcess