前言
最近看到一个多进程的方案,通过启动Service,在子进程渲染视图的方案,在子进程渲染视图会减少和主进程的内存和主进程的渲染,类似于多进程方案,此方案借鉴FlutterEngine的源码,内容使用到Flutter的代码和AIDL的知识,不懂AIDL的同学可以看我的博客,先学习AIDL跨进程通讯
方案
方案实现起来内容不多,暂时只针对渲染的视图来做,如果需要触摸等事件,需要进一步阅读FlutterEngine源码进行适配
- 创建SurfaceView
- 创建Service
- 在Service创建VirtualDisplay
前提
1、在activity_main.xml
定义SurfaceView
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.hensen.mutliprogress.MutliProgressSurfaceView
android:id="@+id/sv"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
自定义SurfaceView会方便扩展
class MutliProgressSurfaceView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : SurfaceView(context, attrs, defStyleAttr) {
}
2、定义AIDL接口
interface IMutliProgressAidlInterface {
void viewCreate(in Surface surface);
}
3、定义Service
<application
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/Theme.MutliProgress">
<!--定义-->
<service
android:name=".MutliProgressService"
android:enabled="true"
android:exported="true"
android:process=":mutliProgress" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
实现
1、创建SurfaceView和启动Service
class MainActivity : AppCompatActivity() {
private var surface: Surface? = null
private var surfaceView: MutliProgressSurfaceView? = null
private var mutliProgressInterface: IMutliProgressAidlInterface? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
surfaceView = findViewById(R.id.sv)
createSurface()
createService()
}
private fun createSurface() {
surfaceView?.holder?.addCallback(object : SurfaceHolder.Callback {
override fun surfaceChanged(p0: SurfaceHolder, p1: Int, p2: Int, p3: Int) {
Log.i("Hensen", "surfaceChanged")
surface = p0.surface
}
override fun surfaceDestroyed(p0: SurfaceHolder) {
}
override fun surfaceCreated(p0: SurfaceHolder) {
}
})
}
private fun createService() {
var intent = Intent()
intent.component = ComponentName(this, MutliProgressService::class.java)
val bindService = bindService(intent, object : ServiceConnection {
override fun onServiceDisconnected(p0: ComponentName?) {
Log.i("Hensen", "onServiceDisconnected")
}
override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
Log.i("Hensen", "onServiceConnected")
mutliProgressInterface = IMutliProgressAidlInterface.Stub.asInterface(p1)
surfaceView?.setInterface(mutliProgressInterface)
surfaceView?.viewCreate(surface)
}
}, Context.BIND_AUTO_CREATE)
}
}
当服务连上之后,通过接口将AIDL接口传递进去后,调用viewCreate()
class MutliProgressSurfaceView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : SurfaceView(context, attrs, defStyleAttr) {
private var mutliProgressInterface: IMutliProgressAidlInterface? = null
public fun setInterface(mutliProgressInterface: IMutliProgressAidlInterface?) {
this.mutliProgressInterface = mutliProgressInterface
}
public fun viewCreate(surface: Surface?) {
mutliProgressInterface?.let {
if (surface != null) {
Log.i("Hensen", "viewCreate")
it.viewCreate(surface)
}
}
}
}
viewCreate()
直接会调用远程服务的方法,并且会传递当前主界面的Surface供子进程承载
class MutliProgressService : Service() {
var presentation: Presentation? = null
var mainHandler = Handler(Looper.getMainLooper())
override fun onBind(p0: Intent?): IBinder? {
return object : IMutliProgressAidlInterface.Stub() {
override fun viewCreate(surface: Surface?) {
Log.i("Hensen", "viewCreate")
mainHandler.post {
val displayManager: DisplayManager =
getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
val dm = resources.displayMetrics
val virtualDisplay: VirtualDisplay = displayManager.createVirtualDisplay(
"bg", dm.widthPixels, dm.heightPixels, dm.densityDpi, surface, 0
)
presentation =
Presentation(this@MutliProgressService, virtualDisplay.display)
val container = FrameLayout(this@MutliProgressService)
container.setBackgroundColor(Color.parseColor("#FF0000"))
presentation?.setContentView(container)
presentation?.show()
}
}
}
}
}
在子进程中通过VirtualDisplay
方式,实现子进程界面的渲染,presentation
源码就是个Dialog,此刻运行代码会发现,在Logcat上会出现两个进程,表示我们成功的在子进程可以渲染我们的View