筆記:WebView

Webview.png

1.webview的組成由哪幾部分組成

答:由四個(gè)部分組成
1.WebSettings 負(fù)責(zé)webview的設(shè)置部分
2.WebViewClient 負(fù)責(zé)webview的生命周期回調(diào)
3.WebViewChromeClient 與Js交互 以及內(nèi)核部分調(diào)度 如彈出彈窗等
4.JavaScriptInstance 負(fù)責(zé)js與native的交互部分

2.為什么打造成組件以及如何實(shí)現(xiàn)的組件化?

打造成組件是為了方便不同的項(xiàng)目導(dǎo)入,實(shí)現(xiàn)方法采用引入AutoService通過(guò)依賴倒置原則 由接口定義方法。

定義接口與實(shí)現(xiàn)

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) {
        ...
    }
}

找到組件,通過(guò)serviceLoader

IWebViewService webImpl = ServiceLoader.load(IWebViewService.class).iterator().next();
webImpl.startLocalPage(...)

2.為什么要使用獨(dú)立進(jìn)程開(kāi)啟webview?

1.webview本身占用的內(nèi)存比較大 容易在性能較差的機(jī)型上導(dǎo)致oom
2.webview需要兼容多種網(wǎng)頁(yè) 新老網(wǎng)頁(yè)格式都有 使用獨(dú)立進(jìn)程可以避免webview加載崩潰導(dǎo)致的app主進(jìn)程崩潰引發(fā)crash

3.進(jìn)程之間的通信與調(diào)度你是如何處理的?

不同進(jìn)程之間的通信是通過(guò)實(shí)現(xiàn)aidl來(lái)完成的

開(kāi)啟單獨(dú)進(jìn)程,在所在的activity下設(shè)置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創(chuàng)建與使用
//創(chuàng)建
// 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);
}
//實(shí)現(xiàn)
... extends IWebviewProcessToMainProcess.Stub{
  @override
    void handleWebCommand(String commandName,String   jsinParams,IMainProcessToWebviewProcessInterface callback){
    }
}
Command命令定義
public interface Command {
      //命令名稱
     String name();
    //命令處理的行為
    void execute(Map parameters, IMainProcessToWebviewProcessInterface callback);
}

命令實(shí)現(xiàn):
@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();
        });
    }
}
調(diào)度器與分發(fā)器
分發(fā)器
public class WebViewProcessCommandDispatcher implements ServiceConnection {
    private static WebViewProcessCommandDispatcher sInstance;
    private IWebviewProcessToMainProcess iWebviewProcessToMainProcess;
    public static WebViewProcessCommandDispatcher getsInstance() {
       //獲取分發(fā)器單例實(shí)例
        return sInstance;
    }
    //創(chuàng)建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();
    }
    //處理命令分發(fā)給調(diào)度器
    public void executeCommand(String commandName, String params, BaseWebView webView){
        if(iWebviewProcessToMainProcess !=null){
            try {
                //aidl實(shí)例 分發(fā)命令
                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 未綁定===");
        }
    }

調(diào)度器

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(){
        //調(diào)度器實(shí)例
        return sInstance;
    }

    public MainProcessCommandManager() {
        //自動(dòng)注冊(cè)命令
        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 {
        //轉(zhuǎn)map 調(diào)度命令
        executeCommand(commandName,new Gson().fromJson(jsinParams, Map.class),callback);
    }

    private void executeCommand(String commandName, Map params,IMainProcessToWebviewProcessInterface callback) {
        Log.d(TAG,"commandName:"+commandName);
          //執(zhí)行命令
        mCommands.get(commandName).execute(params,callback);
    }
  }
}
回調(diào)
通過(guò)回向aidl調(diào)用會(huì)webprocess
iWebviewProcessToMainProcess.handleWebCommand(commandName, params, new IMainProcessToWebviewProcessInterface.Stub() {
                    @Override
                    public void onResult(String callbackname, String response) throws RemoteException {
                        Log.d("ResultNative","回傳Native結(jié)果"+callbackname+"<"+response);
                        webView.handleCallback(callbackname, response);
                    }
                });
//調(diào)用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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容