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

Posted 许英俊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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,实现子进程渲染视图的主要内容,如果未能解决你的问题,请参考以下文章

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

我的Android进阶之旅关于Android使用bindService()绑定服务,onServiceConnected()方法是异步回调的问题以及借鉴NotificationManager来优化(代

我的Android进阶之旅关于Android使用bindService()绑定服务,onServiceConnected()方法是异步回调的问题以及借鉴NotificationManager来优化(代

从刚入测试界到薪资翻倍:聊聊我的测试进阶历程,值得借鉴

AngularJS指令进阶 -- ngModelController详解

Android借鉴博客篇