接上文 我们已经实现了webview在项目里作为一个组件 把webview放在单独的进程里 同时支持webview包含在fragment 或activity里 同时添加了各种loading状态 接下来我们要实现H5与android间通过 js通信
首先我们先定义BaseWebView 继承自WebView 然后把webview一些基本的设置放在basewebview里 实现封装 添加一个register方法把fragment实现的webviewclient 以及WebChromeClient的监听设置进去
然后继续实现js与java的通信 一般来说 我们实现通信的方法 都是 通过@JavascriptInterface 注解 实现与h5约定好的方法实现交互 但这样会有很多@JavascriptInterface方法 我们的webview实现在单独的进程 而大部分的业务逻辑实现在主进程里 所以我们用一种新的办法
我们需要跨进程通信 所以我们新建一个IWebToMainProcessInterface 的AIDL 里面有一个void handlerWebCommand(String commandName,String jsonParams)方法 用于进程间通信
新建类MainProcessCommandsManager 用来接收发往主进程的命令 这个类实现IWebToMainProcessInterface.Stub 方法并且实现单例 新建MainProcessCommandService 在onBind方法里返回MainProcessCommandsManager的单例 接下来 新建WebViewProcessCommandDispatcher 用来发送web的命令 这个类同时也是单例 并且有提供 initAidlConnection方法连接MainProcessCommandService 并且在BaseWebView init的时候调用连接服务 WebViewProcessCommandDispatcher 提供executeCommand 用于使用拿到的IWebToMainProcessInterface发送命令
我们在只定义一个 takeNativeAction(final String jsParam) 方法 所有与原生的交互都通过这个方法来实现 参数是一个json字符串 json里有一个命令名 和命令参数
方法里我们拿到WebViewProcessCommandDispatcher 单例 执行executeCommand 方法 通过aidl 调用到 MainProcessCommandsManager 这样我们的命令就调到了主线程
接下来我们来实现主线程的命令分发
我们新建一个Command 的接口 是所有命令的父类 有name和execute两个方法 其中name 返回命令名字 execute方法执行命令
接下来 在MainProcessCommandsManager 的构造方法中 通过ServiceLoader 拿到所有Command 接口的实现类 并且用HashMap 缓存下来
在执行的时候 只要根据命令名字取出对应的 Command 对象 执行execute方法 就实现了命令的分发
接下来我们来实现命令的回调
首先 在js调用原生的方法的参数json里添加一个callbackName 即js的回调方法名 接下来 新建一个主进程与web进程通信的aidl ICallbackMainToWebProcessInterface
定义一个void handlerCallback(String callBackName,String response); callbackname是回调的js方法名 response是回调给js的参数
在调用WebViewProcessCommandDispatcher.getInstance().executeCommand时把实现ICallbackMainToWebProcessInterface.Stub() 回调传递给command 在具体的命令中回调给web 进程并且
通过 js语句回调给h5 这样就完成了快进程的调用以及回调
详细代码见https://github.com/Semon-Zhang/ProcessWebView 初学写博客 如有不对 请多多指教 欢迎交流