在Android中也可以像pc一样开启多进程,这在android的编程中通常是比较少见的,以为在一个app基本上都是单进程工作就已经足够了,有一些特殊的场景,我们需要用多进程来做一些额外的工作,比如下载工作等。
在Android的AndroidManifest.xml
中,每一个activity
或者service
都可以指定一个进程名称android:process
,当这个activity
或者service
被调用时,该进程自动启动。
因此在android中启动一个进程是比较简单的,如果需要看一个app有几个进程,看AndroidManifest.xml
的android:process
就能知道有几个进程。
建立一个其他进程的service
这里用一个service
建立其他的一个进程。RemoteService
是一个空的service
。代码如下:
class RemoteService : Service() {
private var TAG = "RemoteService"
override fun onBind(intent: Intent?): IBinder? = null
override fun onCreate() {
//Debug.waitForDebugger();
super.onCreate()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return super.onStartCommand(intent, flags, startId)
}
}
在 AndroidManifest.xml
中android:process
的值取为:
android:process=":remote"
这时候,只需要在代码中启动这个服务,进程自然就建立了。
val serviceIntent = Intent(this, RemoteService::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(serviceIntent)
} else {
startService(serviceIntent)
}
可以看到 com.first66.multi_process:remote
的进程已经启动了。
进程间的通讯AIDL
一个app两个进程,就会涉及到两个进程之间的通讯问题,比如一个下载的进程,前端进程需要告诉后台进程要下载哪个链接,后台进程需要告诉前端进程下载的状况。
在android中进程间的通讯可以使用AIDL进行,相当于对服务进行对象的bind
。
创建 IMessageInterface.aidl
的aidl,用来进行两进程间的通讯。
interface IMessageInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void loadData(in String message);
}
这个时候IMessageInterface
只是一个接口而已,相当于一个Binder
需要进行实例化。
在RemoteService.kt
中创建一个Binder
,当每个对象要来绑定这个服务的时候,我们返回这个Binder
给他。
private var binder:Binder = object : IMessageInterface.Stub() {
override fun loadData(message: String?) {
message?.let {
Log.d(TAG,it)
}
}
}
绑定的时候,把这个Binder
给另一个进程。
override fun onBind(intent: Intent?): IBinder? {
return binder
}
在MainActivity
启动这个服务进程的时候,创建一个ServiceConnection
当服务绑定成功了以后,返回Binder
。
private var iMessageAidlInterface: IMessageInterface? = null
private var serviceConnection: ServiceConnection = object : ServiceConnection{
override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
iMessageAidlInterface = IMessageInterface.Stub.asInterface(p1)
iMessageAidlInterface?.loadData("Hello Message")
}
override fun onServiceDisconnected(p0: ComponentName?) {
}
}
onServiceConnected
连接成功了以后会IBinder
返回给启动的进程,这个就能给另外一个进程传递消息了。
进程间的调试
在调试的时候,下的断点必须是在同一个进程间才能够停的住,如果是处在不同的进程,即使下了断点也是会变黑的。
可以在另外一个进程服务中onCreate
加入:
Debug.waitForDebugger();
当启动服务的时候,点击另外一个进程,断点才能起作用。
查看进程:
点击 com.first66.multi_process:remote
进入调试。