使用SurfaceControlViewHost 实现跨进程UI

2023-10-13  本文已影响0人  凤梨大酥

SurfaceControlViewHost是Android 11中加入的一个新工具类,其在Google文档中的描述如下:

Utility class for adding a View hierarchy to a [SurfaceControl](https://developer.android.com/reference/android/view/SurfaceControl). The View hierarchy will render in to a root SurfaceControl, and receive input based on the SurfaceControl's placement on-screen. The primary usage of this class is to embed a View hierarchy from one process in to another. After the SurfaceControlViewHost has been set up in the embedded content provider, we can send the [SurfaceControlViewHost.SurfacePackage](https://developer.android.com/reference/android/view/SurfaceControlViewHost.SurfacePackage) to the host process. The host process can then attach the hierarchy to a SurfaceView within its own by calling [SurfaceView#setChildSurfacePackage](https://developer.android.com/reference/android/view/SurfaceView#setChildSurfacePackage(android.view.SurfaceControlViewHost.SurfacePackage)).

简单来说这是一个提供了跨进程UI渲染的工具类,SurfaceControlViewHost的作用类似于一个特殊的Window容器。不同的是,这个容器中的View hierarchy并不是直接在本地的Canvas上进行绘制,而是绑定到了一个SurfaceView中,这种绑定是通过Binder机制实现的,为跨进程使用而设计。

RemoteViews这种虚假的跨进城UI机制相比,SurfaceControlViewHost提供的能力可以说有天壤之别。
1,SurfaceControlViewHost支持所有的View子类,包括开发者在本地自定义的控件,支持使用任何定义在本地的资源。
2,SurfaceControlViewHost支持触摸事件传递,开发者可以直接使用View.onClickListenerdispatchMotionEvent等熟悉的机制完成复杂的交互开发。
3,SurfaceControlViewHost渲染的性能和在本地Window中几乎没有区别。
4,SurfaceControlViewHost绑定使用的SurfacePackage对象是完全与业务数据无关的,所有的业务逻辑都发生在本地进程,开发者无需担心在远端进程集成功能组件时有安全性问题。

要理解为什么SurfaceControlViewHost能够提供如此强大的功能,需要我们对Android系统上的渲染机制有一定的了解。我们知道,每个Activity(或者DialogPopupWindow)所具有的Window对象,其实都在WindowManager的管理下,对应着一个SurfaceFlinger中的Surface对象,而Surface对象的本质,可以简单的理解为一个内存中的绘制缓存区,代表了一个可以绘制的图层。系统渲染时,首先通过Canvas记录了所有绘制数据,再传递给SurfaceFlinger在图层上做实际的绘制计算,然后再将其合成为真正的屏幕帧。
同时我们知道,SurfaceView是一个特殊的控件,它并不在所在Window上进行绘制,而是具有一个独立的Surface,用于提供给某些媒体进行渲染(最常见的如视频播放器或者摄像头硬件)。
因此我们知道,渲染的过程本来就是跨进程的,只要能获得一个Surface句柄,拥有系统权限的代码就可以直接在这个Surface对应的图层上进行绘制。而SurfaceControlViewHost就是这样一个工具,帮助我们将本地的View hierarchy和远端的SurfaceView绑定起来,实现跨进程渲染。

说了这么多,可能大家对怎么应用还是一头雾水,这里有一个我写的demo,参考了国外一位大神的文章

对于这个demo,有以下几点说明:
1,通信方式使用了Messenger模式,使用aidl可以得到同样的效果。
2,不支持EditText唤醒输入法,这个需要自己实现,一个比较简单的替代是点击之后启动一个Activity来获取输入。
3,直接使用SurfaceView.setZOrderOnTop的方式来传递触摸事件会造成对系统UI的遮挡,因此demo中自行通过binder传递触摸事件,这样做的一个好处是为将来在远端和本地之间转移事件的处理权提供了灵活性。

上一篇 下一篇

猜你喜欢

热点阅读