美文网首页
笔记:WebView

笔记:WebView

作者: 盐海里的鱼 | 来源:发表于2020-12-06 23:06 被阅读0次
Webview.png

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);
                }
            });
        }
    }

https://gitee.com/DaiMaZhiJia/WebViewDemoControler

相关文章

  • h5学习总结

    webview文章 【1】webview的使用总结 h5的学习笔记 【2】

  • WebView调试

    文章仅做个人笔记使用: chrome浏览器自带的 webview调试 需要在代码中配置: WebView....

  • WebView笔记

    显示百度网页: 布局 加载本地HTML 本地新建assets文件夹 代码调用: //webView 显示Html语...

  • WebView 笔记

    看这里看这里,都从这里来的:Android:这是一份全面 & 详细的Webview使用攻略最全面总结 Androi...

  • 笔记:WebView

    1.webview的组成由哪几部分组成 答:由四个部分组成1.WebSettings 负责webview的设置部分...

  • WebView笔记

  • android WebView-动态修改网页内容

    做个笔记以备后用!!! 在webview开发过程中有时候遇到用webView需要加载某网站,网页中有些logo,文...

  • WebView基础

    之前webView的使用很大多局限于显示网页,现在有机会重头梳理下整理成如下笔记: 基本用法 WebView 的状...

  • Webview 整理笔记

    初始化操作及常见用法 WebSettings、WebViewClient、WebChromeClient 的常用方...

  • Android WebView笔记

    Android 25版本的webview源码: 可以看到都是由provider去处理的provider初始化的地方...

网友评论

      本文标题:笔记:WebView

      本文链接:https://www.haomeiwen.com/subject/kjnawktx.html