1.webview的组成由哪几部分组成
答:由四个部分组成
1.WebSettings 负责webview的设置部分
2.WebViewClient 负责webview的生命周期回调
3.WebViewChromeClient 与Js交互 以及内核部分调度 如弹出弹窗等
4.JavaScriptInstance 负责js与native的交互部分
2.为什么打造成组件以及如何实现的组件化?
打造成组件是为了方便不同的项目导入,实现方法采用引入AutoService通过依赖倒置原则 由接口定义方法。
定义接口与实现
public interface IWebViewService {
void startWebViewActivity(Context context, String url,String title,boolean isShowActionBar);
Fragment getWebViewFragment(String url,boolean needNativeRefresh);
void startLocalPage(Context context);
}
@AutoService({IWebViewService.class})
public class WebViewServiceImpl implements IWebViewService {
@Override
public void startWebViewActivity(Context context, String url, String title,boolean isShowActionBar) {
....
}
@Override
public Fragment getWebViewFragment(String url,boolean needNativeRefresh) {
` ...
}
@Override
public void startLocalPage(Context context) {
...
}
}
找到组件,通过serviceLoader
IWebViewService webImpl = ServiceLoader.load(IWebViewService.class).iterator().next();
webImpl.startLocalPage(...)
2.为什么要使用独立进程开启webview?
1.webview本身占用的内存比较大 容易在性能较差的机型上导致oom
2.webview需要兼容多种网页 新老网页格式都有 使用独立进程可以避免webview加载崩溃导致的app主进程崩溃引发crash
3.进程之间的通信与调度你是如何处理的?
不同进程之间的通信是通过实现aidl来完成的
开启单独进程,在所在的activity下设置process属性
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.chenx.webview">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application android:usesCleartextTraffic="true">
<activity android:name=".webviewprocess.WebViewActivity"
android:process=":myWebView"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"></activity>
<service android:name=".mainprocess.MainProcessCommandService"/>
</application>
</manifest>
aidl创建与使用
//创建
// IWebviewProcessToMainProcess.aidl
package com.chenx.webview;
// Declare any non-default types here with import statements
import com.chenx.webview.IMainProcessToWebviewProcessInterface;
interface IWebviewProcessToMainProcess {
void handleWebCommand(String commandName,String jsinParams,IMainProcessToWebviewProcessInterface callback);
}
//实现
... extends IWebviewProcessToMainProcess.Stub{
@override
void handleWebCommand(String commandName,String jsinParams,IMainProcessToWebviewProcessInterface callback){
}
}
Command命令定义
public interface Command {
//命令名称
String name();
//命令处理的行为
void execute(Map parameters, IMainProcessToWebviewProcessInterface callback);
}
命令实现:
@AutoService({Command.class})
public class ToastCommand implements Command {
@Override
public String name() {
return "showToast";
}
@Override
public void execute(Map parameters, IMainProcessToWebviewProcessInterface callback) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(()->{
Toast.makeText(BaseApplication.sApplication, String.valueOf(parameters.get("message")), Toast.LENGTH_SHORT).show();
});
}
}
调度器与分发器
分发器
public class WebViewProcessCommandDispatcher implements ServiceConnection {
private static WebViewProcessCommandDispatcher sInstance;
private IWebviewProcessToMainProcess iWebviewProcessToMainProcess;
public static WebViewProcessCommandDispatcher getsInstance() {
//获取分发器单例实例
return sInstance;
}
//创建Aidl连接
public void initAidlConnection(){
Intent intent = new Intent(BaseApplication.sApplication, MainProcessCommandService.class);
BaseApplication.sApplication.bindService(intent,this, Context.BIND_AUTO_CREATE);
}
@Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
iWebviewProcessToMainProcess = IWebviewProcessToMainProcess.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
iWebviewProcessToMainProcess = null;
initAidlConnection();
}
@Override
public void onBindingDied(ComponentName name) {
iWebviewProcessToMainProcess = null;
initAidlConnection();
}
//处理命令分发给调度器
public void executeCommand(String commandName, String params, BaseWebView webView){
if(iWebviewProcessToMainProcess !=null){
try {
//aidl实例 分发命令
iWebviewProcessToMainProcess.handleWebCommand(commandName, params,
new IMainProcessToWebviewProcessInterface.Stub() {
@Override
public void onResult(String callbackname, String response) throws RemoteException {
webView.handleCallback(callbackname, response);
}
});
} catch (RemoteException e) {
e.printStackTrace();
}
}else{
Log.e(BaseWebView.TAG,"iWebviewProcessToMainProcess 未绑定===");
}
}
调度器
public class MainProcessCommandManager extends IWebviewProcessToMainProcess.Stub{
private static final String TAG = "MainProcess";
public static MainProcessCommandManager sInstance;
private static Map<String, Command> mCommands = new HashMap<>();
public static MainProcessCommandManager getInstance(){
//调度器实例
return sInstance;
}
public MainProcessCommandManager() {
//自动注册命令
ServiceLoader<Command> serviceLoader = ServiceLoader.load(Command.class);
for (Command command:serviceLoader) {
if(!mCommands.containsKey(command.name())){
mCommands.put(command.name(),command);
}
}
}
@Override
public void handleWebCommand(String commandName, String jsinParams, IMainProcessToWebviewProcessInterface callback) throws RemoteException {
//转map 调度命令
executeCommand(commandName,new Gson().fromJson(jsinParams, Map.class),callback);
}
private void executeCommand(String commandName, Map params,IMainProcessToWebviewProcessInterface callback) {
Log.d(TAG,"commandName:"+commandName);
//执行命令
mCommands.get(commandName).execute(params,callback);
}
}
}
回调
通过回向aidl调用会webprocess
iWebviewProcessToMainProcess.handleWebCommand(commandName, params, new IMainProcessToWebviewProcessInterface.Stub() {
@Override
public void onResult(String callbackname, String response) throws RemoteException {
Log.d("ResultNative","回传Native结果"+callbackname+"<"+response);
webView.handleCallback(callbackname, response);
}
});
//调用evaluateJavascript注入js
public void handleCallback(String callbackname, String response) {
if(!TextUtils.isEmpty(callbackname)&&!TextUtils.isEmpty(response)){
String jscode = "javascript:xiangxuejs.callback('"+callbackname+"',"+response+")";
Log.d("callBackData",callbackname+":"+response);
post(new Runnable() {
@Override
public void run() {
evaluateJavascript(jscode,null);
}
});
}
}
网友评论