最近看到一个多进程的方案,通过启动Service,在子进程渲染视图的方案,在子进程渲染视图会减少和主进程的内存和主进程的渲染,类似于多进程方案,此方案借鉴FlutterEngine的源码,内容使用到Flutter的代码和AIDL的知识,不懂AIDL的同学可以看我的博客,先学习AIDL跨进程通讯
方案实现起来内容不多,暂时只针对渲染的视图来做,如果需要触摸等事件,需要进一步阅读FlutterEngine源码进行适配
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