Android进阶——借鉴FlutterEngine,实现子进程渲染视图

前言

最近看到一个多进程的方案,通过启动Service,在子进程渲染视图的方案,在子进程渲染视图会减少和主进程的内存和主进程的渲染,类似于多进程方案,此方案借鉴FlutterEngine的源码,内容使用到Flutter的代码和AIDL的知识,不懂AIDL的同学可以看我的博客,先学习AIDL跨进程通讯

方案

方案实现起来内容不多,暂时只针对渲染的视图来做,如果需要触摸等事件,需要进一步阅读FlutterEngine源码进行适配

  1. 创建SurfaceView
  2. 创建Service
  3. 在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

Android进阶——借鉴FlutterEngine,实现子进程渲染视图

上一篇:Gmsh 四面体单元剖分(二)


下一篇:使用cairo取出子图