本项目用于验证 Android 是否能够跨进程渲染 View,最终实现了在子进程创建WebView,主进程显示的功能。

一、跨进程渲染的意义

  • 有一些组件比如 WebView 如果在主进程初始化,会大大增加主进程的内存占用。
  • 部分组件设计时只支持特定进程,但是又想在别的进程显示该组件的View
  • 一些其它限制...

二、跨进程渲染的实现

1.提供一个Surface

跨进程渲染,需要一个Surface对象,本项目中使用SurfaceView提供。

Surface实现了Parcelable接口,也就意味着它可以跨进程传递。

具体逻辑参考:ProcessSurfaceView,通过bindService拉起子进程Service后,将Surface通过接口传递给了子进程。

// bindService 拉起子进程
private fun bindService() {
val intent = Intent(context, RemoteDrawService::class.java)
context.bindService(intent, this@ProcessSurfaceView, Context.BIND_AUTO_CREATE or Context.BIND_IMPORTANT)
} // 子进程连接后,拿到 AIDL 接口传递 Surface 到子进程
override fun onServiceConnected(p0: ComponentName?, iBinder: IBinder?) {
Log.i(TAG, "onServiceConnected")
if (iBinder == null) {
Log.e(TAG, "onServiceDisconnected: iBinder is null.")
return
}
iRemoteDraw = IRemoteDraw.Stub.asInterface(iBinder)
setSurfaceToRemote()
}

ps:SurfaceView退后台需要额外处理,本项目中是在退后台后重新创建了渲染的View。

2.子进程创建View

收到主进程的Surface后,需要创建VirtualDisplayPresentation

val displayManager = service.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
val dm = service.resources.displayMetrics
val virtualDisplay = displayManager.createVirtualDisplay("", dm.widthPixels, dm.heightPixels, dm.densityDpi, surface, 0)
val presentation = Presentation(service, virtualDisplay.display)
presentation.setContentView(createView())
presentation.show()

至此,就实现了跨进程渲染。效果如下:

3.点击事件处理

由于渲染的View是在另外一个进程,所以收不到点击事件。这里的实现方案是将SurfaceView的点击事件跨进程传递到子进程。

override fun dispatchTouchEvent(event: MotionEvent?): Boolean {
return iRemoteDraw?.dispatchTouchEvent(event) ?: false
}

由于是跨进程传递,事件的处理效率肯定变低了。因此跨进程渲染适合那些不怎么依赖点击事件的显示,比如播放视频。

三、优点和缺点

可见跨进程渲染的显示还是相对简单的,系统提供了相应的能力。使用时,需要注意其的限制。

1.优点

  • 将渲染交给了其它进程,降低了本进程内存占用。
  • 有一些业务场景只能通过跨进程渲染实现。

2.缺点

  • 需要额外处理点击事件。包括如果需要跟渲染对象进行交互,都需要提供跨进程接口,处理效率变低。
  • 复杂程度变高。

最新文章

  1. 《Entity Framework 6 Recipes》中文翻译系列 (11) -----第三章 查询之异步查询
  2. [Java入门笔记] 面向对象编程基础(二):方法详解
  3. 深入理解JVM内幕(转)
  4. 在Mac mini上编译Android源码
  5. 基于LoadRunner构建接口测试框架
  6. Facebook开源项目:我们为什么要用Fresco框架?
  7. 取caml查询结果的前多少行
  8. GUID是什么意思及Guid在sqlserver中的使用
  9. 面试后 follow up letter 分享
  10. 个人自建网店(WordPress WooCommerce on SAE)集成支付宝支付
  11. 关于js中两种定时器的设置及清除(转载)
  12. Java基础-Random类(05)
  13. oracle11g导出表时会发现少表,空表导不出解决方案
  14. Connection open error . Connection Timeout Expired. The timeout period elapsed during the post-login phase.
  15. 【原创】大数据基础之Impala(2)实现细节
  16. springmvc java配置
  17. Setting property 'source' to 'org.eclipse.jst.jee.server:hczm' did not find a matching property
  18. 《剑指offer》 二进制中1的个数
  19. mongodb副本集 statestr状态说明/解释
  20. Delphi:基于jcl的Bugsplat Crash收集单元

热门文章

  1. 【java】学习路径28-Java集合类知识点总结+练习题(去重)
  2. 第七十七篇:ref引用(在vue中引用组件实例)
  3. Skype for Business server 数据库安装
  4. Python数据科学手册-Numpy数组的计算:比较、掩码和布尔逻辑,花哨的索引
  5. 2.1pip的安装和使用
  6. 第六章:Django 综合篇 - 12:聚合内容 RSS/Atom
  7. x-pack设置完毕后,es-head无法登陆的问题, 登录需要账号密码的问题
  8. Docker与Containerd使用区别
  9. ProxySQL Main库
  10. CentOS7下的lvm(逻辑卷)在线扩容