Android高级UI之webview架构搭建(组件化module)

一、webView组件化搭建

package com.example.webview;

import android.os.Bundle;
import android.view.View;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;

import com.example.webview.databinding.ActivityWebviewBinding;
import com.example.webview.utils.Constants;

public class WebViewActivity extends AppCompatActivity {
    ActivityWebviewBinding mBinding;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_webview);
        mBinding.webview.getSettings().setJavaScriptEnabled(true);//一定要加 否则报错
        mBinding.webview.loadUrl("https://www.baidu.com/");//若要用http需在application中添加设置android:useCleartextTraffic="true"
        mBinding.title.setText(getIntent().getStringExtra(Constants.TITLE));
        mBinding.actionBar.setVisibility(getIntent().getBooleanExtra(Constants.IS_SHOW_ACTION_BAR, true)? View.VISIBLE:View.GONE);
        mBinding.back.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                WebViewActivity.this.finish();
            }
        });
    }
}

android:useCleartextTraffic=“true”
==》解决打不开页面的问题,设置允许HTTP请求

如何实现组件化?
arouter or cc(个人开发者)方式实现组件化

aotoService实现组件化的方式
第一步:添加依赖

annotationProcessor 'com.google.auto.service:auto-service:1.0-rc7'
implementation 'com.google.auto.service:auto-service:1.0-rc7'

第二步:新增common module并添加接口类——组件下沉(implementation project(":common"))

package com.example.common.autoservice;

import android.content.Context;

public interface IWebViewService {
    void startWebViewActivity(Context context, String url, String title, boolean showActionBar);
}

第三步:创建接口实现类并用注解@autoService标注

package com.example.webview;

import android.content.Context;
import android.content.Intent;

import com.example.common.autoservice.IWebViewService;
import com.example.webview.utils.Constants;
import com.google.auto.service.AutoService;

@AutoService({IWebViewService.class})
public class WebViewServiceImpl implements IWebViewService {
    @Override
    public void startWebViewActivity(Context context, String url, String title, boolean isShowActionBar) {
        if (context != null) {
            Intent intent = new Intent(context, WebViewActivity.class);
            intent.putExtra(Constants.TITLE, title);
            intent.putExtra(Constants.URL, url);
            intent.putExtra(Constants.IS_SHOW_ACTION_BAR, isShowActionBar);
            context.startActivity(intent);
        }
    }
}

第四步:关于ServiceLoader的设置及操作

case R.id.btn_webview:
   -      //startActivity(new Intent(UIDemoActivity.this, WebViewActivity.class));
            // 组件化方式
 +           IWebViewService webViewService = ServiceLoader.load(IWebViewService.class).iterator().next();
+          if (webViewService != null){
+                webViewService.startWebViewActivity(this, "https://www.baidu.com/", "百度", false);
 }
 break;

但迭代器的写法需要优化,故对ServiceLoader做封装,新增一个base的module做处理

package com.example.base.autoservice;

import java.util.ServiceLoader;

public final class CustomServiceLoader {
    private CustomServiceLoader() {
    }

    public static  S load(Class service) {
        try {
            return ServiceLoader.load(service).iterator().next();
        } catch (Exception e) {
            return null;
        }
    }
}
 case R.id.btn_webview:
-         //IWebViewService webViewService = ServiceLoader.load(IWebViewService.class).iterator().next();
+           IWebViewService webViewService = CustomServiceLoader.load(IWebViewService.class);
         if (webViewService != null){
             webViewService.startWebViewActivity(this, "https://www.baidu.com/", "百度", false);
         }
         break;

第五步:用组件化实现展示百度首页并控制是否显示ActionBar

小便签:
app的build.gradle中的引入jar包最好以文件的形式依赖,否则可能后续维护有困难,删除 implementation fileTree(dir: 'libs', include: ['*.jar'])
api与implement分别相当于Java中的public和private 
将通用版本号统一设置到 rootProject 中——加入到ext(对应项目的build.gradle)

二、WebView在Fragment中的使用及组成部分

组件化(autoService比Arouter简单可靠 cc基于字符串) 模块化 层次化 控件化

kotlin实现时找不到autoService时需要添加三个插件,特别是kotlin-kapt,相当于Java的AnnotationProcessor

第一步:支持Fragment方式打开

package com.example.webview;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;

import com.example.webview.databinding.FragmentWebviewBinding;
import com.example.webview.utils.Constants;

public class WebViewFragment extends Fragment {
    private String mUrl;
    private FragmentWebviewBinding mBinding;

    public static WebViewFragment newInstance(String url/*, boolean canNativeRefresh*/) {
        WebViewFragment fragment = new WebViewFragment();
        Bundle bundle = new Bundle();
        bundle.putString(Constants.URL, url);
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle bundle = getArguments();
        if (bundle != null) {
            mUrl = bundle.getString(Constants.URL);
        }
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_webview, container, false);
        mBinding.webview.getSettings().setJavaScriptEnabled(true);
        mBinding.webview.loadUrl(mUrl);
        return mBinding.getRoot();
    }
}

第二步:打开时有空白显示需添加进度条(webViewClient)——loadsir第三方控件 + 第三方Lottie动画

api 'com.kingja.loadsir:loadsir:1.3.6'
implementation 'com.airbnb.android:lottie:2.8.0'
package com.example.practicedemo;

import com.example.base.BaseApplication;
import com.example.base.loadsir.CustomCallback;
import com.example.base.loadsir.EmptyCallback;
import com.example.base.loadsir.ErrorCallback;
import com.example.base.loadsir.LoadingCallback;
import com.example.base.loadsir.TimeoutCallback;
import com.kingja.loadsir.core.LoadSir;

public class WebViewApplication extends BaseApplication{
    @Override
    public void onCreate() {
        super.onCreate();
        LoadSir.beginBuilder()
                .addCallback(new ErrorCallback())
                .addCallback(new EmptyCallback())
                .addCallback(new LoadingCallback())
                .addCallback(new TimeoutCallback())
                .addCallback(new CustomCallback())
                .setDefaultCallback(LoadingCallback.class)
                .commit();
    }
}

WebViewActivity.java

 private void initWebViewFragment() {
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        Fragment fragment = WebViewFragment.newInstance(getIntent().getStringExtra(Constants.URL));
        ft.replace(R.id.web_view_fragment, fragment).commit();
    }
package com.example.webview;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebViewClient;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;

import com.example.base.loadsir.ErrorCallback;
import com.example.base.loadsir.LoadingCallback;
import com.example.webview.databinding.FragmentWebviewBinding;
import com.example.webview.utils.Constants;
import com.example.webview.webviewclient.CustomWebviewClient;
import com.kingja.loadsir.callback.Callback;
import com.kingja.loadsir.core.LoadService;
import com.kingja.loadsir.core.LoadSir;

public class WebViewFragment extends Fragment implements WebViewCallback {
    private static final String TAG = "WebViewFragment";
    private String mUrl;
    private FragmentWebviewBinding mBinding;
    private LoadService mLoadService;
    private boolean mIsError = false;

    public static WebViewFragment newInstance(String url) {
        WebViewFragment fragment = new WebViewFragment();
        Bundle bundle = new Bundle();
        bundle.putString(Constants.URL, url);
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle bundle = getArguments();
        if (bundle != null) {
            mUrl = bundle.getString(Constants.URL);
        }
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_webview, container, false);
        mBinding.webview.getSettings().setJavaScriptEnabled(true);
        mBinding.webview.loadUrl(mUrl);
+        mBinding.webview.setWebViewClient(new CustomWebviewClient(this));
+        mLoadService = LoadSir.getDefault().register(mBinding.webview, new Callback.OnReloadListener() {
+            @Override
+            public void onReload(View v) {
+                mLoadService.showCallback(LoadingCallback.class);
+                mBinding.webview.reload();
            }
        });
-       // return mBinding.getRoot();
+        return mLoadService.getLoadLayout();
    }

    @Override
+    public void pageStarted(String url) {
+        if (mLoadService != null) {
+            mLoadService.showCallback(LoadingCallback.class);
+        }
    }

    @Override
+    public void pageFinished(String url) {
+        if (mLoadService != null) {
+            if(mIsError){
+                mLoadService.showCallback(ErrorCallback.class);
+            }   else {
+                mLoadService.showSuccess();
            }
        }
    }

    @Override
+    public void onError() {
+        Log.e(TAG, "onError");
+        mIsError = true;
    }
}

此处需要知道WebViewClient 的作用,处理各种通知、请求事件,当查询完成或者刷新完成后对控件的状态做控制

package com.example.webview.webviewclient;

import android.graphics.Bitmap;
import android.util.Log;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.example.webview.WebViewCallback;

public class CustomWebviewClient extends WebViewClient {
    private WebViewCallback mWebViewCallBack;
    private static final String TAG = "CustomWebviewClient";

    public CustomWebviewClient(WebViewCallback callBack){
        this.mWebViewCallBack = callBack;
    }

    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        if(mWebViewCallBack != null) {
            mWebViewCallBack.pageStarted(url);
        } else {
            Log.e(TAG, "WebViewCallBack is null.");
        }
    }

    @Override
    public void onPageFinished(WebView view, String url) {
        if(mWebViewCallBack != null) {
            mWebViewCallBack.pageFinished(url);
        } else {
            Log.e(TAG, "WebViewCallBack is null.");
        }
    }

    @Override
    public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
        super.onReceivedError(view, request, error);
        if(mWebViewCallBack != null) {
            mWebViewCallBack.onError();
        } else {
            Log.e(TAG, "WebViewCallBack is null.");
        }
    }
}
package com.example.webview;

public interface WebViewCallback {
    void pageStarted(String url);
    void pageFinished(String url);
    void onError();
}

第三步:下拉刷新功能实现 + 各种状态(如错误界面的回调处理)

api 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0-alpha-7'

布局中包一层下拉刷新控件




    

        
    

package com.example.webview;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebViewClient;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;

import com.example.base.loadsir.ErrorCallback;
import com.example.base.loadsir.LoadingCallback;
import com.example.webview.databinding.FragmentWebviewBinding;
import com.example.webview.utils.Constants;
import com.example.webview.webviewclient.CustomWebviewClient;
import com.kingja.loadsir.callback.Callback;
import com.kingja.loadsir.core.LoadService;
import com.kingja.loadsir.core.LoadSir;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.scwang.smartrefresh.layout.listener.OnRefreshListener;

public class WebViewFragment extends Fragment implements WebViewCallback, OnRefreshListener {
    private static final String TAG = "WebViewFragment";
    private String mUrl;
    private FragmentWebviewBinding mBinding;
    private LoadService mLoadService;
    private boolean mIsError = false;
    private boolean mCanNativeRefresh;

    public static WebViewFragment newInstance(String url, boolean canNativeRefresh) {
        WebViewFragment fragment = new WebViewFragment();
        Bundle bundle = new Bundle();
        bundle.putString(Constants.URL, url);
+        bundle.putBoolean(Constants.CAN_NATIVE_REFRESH, canNativeRefresh);
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle bundle = getArguments();
        if (bundle != null) {
            mUrl = bundle.getString(Constants.URL);
+            mCanNativeRefresh = bundle.getBoolean(Constants.CAN_NATIVE_REFRESH);
        }
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_webview, container, false);
        mBinding.webview.getSettings().setJavaScriptEnabled(true);
        mBinding.webview.loadUrl(mUrl);
        mBinding.webview.setWebViewClient(new CustomWebviewClient(this));
+        mLoadService = LoadSir.getDefault().register(mBinding.smartrefreshlayout, new Callback.OnReloadListener() {
            @Override
            public void onReload(View v) {
                mLoadService.showCallback(LoadingCallback.class);
                mBinding.webview.reload();
            }
        });

+        mBinding.smartrefreshlayout.setOnRefreshListener(this);
+        mBinding.smartrefreshlayout.setEnableRefresh(mCanNativeRefresh);
+        mBinding.smartrefreshlayout.setEnableLoadMore(false);

       // return mBinding.getRoot();
        return mLoadService.getLoadLayout();
    }

    @Override
    public void pageStarted(String url) {
        if (mLoadService != null) {
            mLoadService.showCallback(LoadingCallback.class);
        }
    }

    @Override
    public void pageFinished(String url) {
+        if(mIsError) {
+            mBinding.smartrefreshlayout.setEnableRefresh(true);
+        } else {
+            mBinding.smartrefreshlayout.setEnableRefresh(mCanNativeRefresh);
        }
        Log.d(TAG, "pageFinished");
+        mBinding.smartrefreshlayout.finishRefresh();
        if (mLoadService != null) {
            if(mIsError){
                mLoadService.showCallback(ErrorCallback.class);
            }   else {
                mLoadService.showSuccess();
            }
        }
    }

    @Override
    public void onError() {
        Log.e(TAG, "onError");
        mIsError = true;
+        mBinding.smartrefreshlayout.finishRefresh();
    }

    @Override
+    public void onRefresh(@NonNull RefreshLayout refreshLayout) {
+        mBinding.webview.reload();
    }
}

第四步:标题栏设置为对应网页标题——WebChromeClient.onReceivedTitle()

package com.example.webview.webchromeclient;

import android.util.Log;
import android.webkit.WebChromeClient;
import android.webkit.WebView;

import com.example.webview.WebViewCallback;

public class CustomWebChromeClient extends WebChromeClient {
    private WebViewCallback mWebViewCallBack;
    private static final String TAG = "CustomWebChromeClient";

    public CustomWebChromeClient(WebViewCallback callBack){
        this.mWebViewCallBack = callBack;
    }

    @Override
    public void onReceivedTitle(WebView view, String title) {
        if(mWebViewCallBack != null) {
            mWebViewCallBack.updateTitle(title);
        } else {
            Log.e(TAG, "WebViewCallBack is null.");
        }
    }
}
package com.example.webview;
import ..........

public class WebViewFragment extends Fragment implements WebViewCallback, OnRefreshListener {
 ......
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_webview, container, false);
        mBinding.webview.getSettings().setJavaScriptEnabled(true);
        mBinding.webview.loadUrl(mUrl);
        mBinding.webview.setWebViewClient(new CustomWebviewClient(this));
        mLoadService = LoadSir.getDefault().register(mBinding.smartrefreshlayout, new Callback.OnReloadListener() {
            @Override
            public void onReload(View v) {
                mLoadService.showCallback(LoadingCallback.class);
                mBinding.webview.reload();
            }
        });

        mBinding.smartrefreshlayout.setOnRefreshListener(this);
        mBinding.smartrefreshlayout.setEnableRefresh(mCanNativeRefresh);
        mBinding.smartrefreshlayout.setEnableLoadMore(false);

+        mBinding.webview.setWebChromeClient(new CustomWebChromeClient(this));
       // return mBinding.getRoot();
        return mLoadService.getLoadLayout();
    }
  .......
    @Override
+    public void updateTitle(String title) {
+        if (getActivity() instanceof WebViewActivity){
+            ((WebViewActivity)getActivity()).updateTitle(title);
        }
    }
........
}

WebViewActivity.java

public void updateTitle(String title) {
        mBinding.title.setText(title);
    }

webView的组成部分(四部分)

webview组成名称 作用及常用方法
WebView 创建对象/加载URL/生命周期管理/状态管理
WebViewClient 处理各种通知、请求事件—onPageStarted onPageFinished
WebChromeClient 辅助WebView处理JS对话框
WebSettings 配置/管理WebView

三、WebView与native的通信

自定义WebSettings

package com.example.webview.settings;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.util.Log;
import android.webkit.WebSettings;
import android.webkit.WebView;

import com.example.webview.BuildConfig;

public class WebViewDefaultSettings {
    private WebSettings mWebSettings;

    public static WebViewDefaultSettings getInstance(){
        return new WebViewDefaultSettings();
    }

    private WebViewDefaultSettings(){
    }

    private static boolean isNetworkConnected(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = cm.getActiveNetworkInfo();
        if (networkInfo != null) {
            boolean a = networkInfo.isConnected();
            return a;
        } else {
            return false;
        }
    }
    public void setSettings(WebView webView) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            webView.enableSlowWholeDocumentDraw();
        }
        mWebSettings = webView.getSettings();
        mWebSettings.setJavaScriptEnabled(true);
        mWebSettings.setSupportZoom(true);
        mWebSettings.setBuiltInZoomControls(false);
        if (isNetworkConnected(webView.getContext())) {
            mWebSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
        } else {
            mWebSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mWebSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }

        // 硬件加速兼容性问题有点多
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//            webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
//        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//            webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
//        } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
//            webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
//        }

        mWebSettings.setTextZoom(100);
        mWebSettings.setDatabaseEnabled(true);
        mWebSettings.setAppCacheEnabled(true);
        mWebSettings.setLoadsImagesAutomatically(true);
        mWebSettings.setSupportMultipleWindows(false);
        mWebSettings.setBlockNetworkImage(false);//是否阻塞加载网络图片  协议http or https
        mWebSettings.setAllowFileAccess(true); //允许加载本地文件html  file协议
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            mWebSettings.setAllowFileAccessFromFileURLs(false); //通过 file url 加载的 Javascript 读取其他的本地文件 .建议关闭
            mWebSettings.setAllowUniversalAccessFromFileURLs(false);//允许通过 file url 加载的 Javascript 可以访问其他的源,包括其他的文件和 http,https 等其他的源
        }
        mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

            mWebSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
        } else {
            mWebSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);
        }
        mWebSettings.setSavePassword(false);
        mWebSettings.setSaveFormData(false);
        mWebSettings.setLoadWithOverviewMode(true);
        mWebSettings.setUseWideViewPort(true);
        mWebSettings.setDomStorageEnabled(true);
        mWebSettings.setNeedInitialFocus(true);
        mWebSettings.setDefaultTextEncodingName("utf-8");//设置编码格式
        mWebSettings.setDefaultFontSize(16);
        mWebSettings.setMinimumFontSize(10);//设置 WebView 支持的最小字体大小,默认为 8
        mWebSettings.setGeolocationEnabled(true);
        mWebSettings.setUseWideViewPort(true);

        String appCacheDir = webView.getContext().getDir("cache", Context.MODE_PRIVATE).getPath();
        Log.i("WebSetting", "WebView cache dir: " + appCacheDir);
        mWebSettings.setDatabasePath(appCacheDir);
        mWebSettings.setAppCachePath(appCacheDir);
        mWebSettings.setAppCacheMaxSize(1024*1024*80);

        // 用户可以自己设置useragent
        // mWebSettings.setUserAgentString("webprogress/build you agent info");

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            webView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG);
        }
    }
}

WebViewFragment.java中使用自己写的WebSettings

 @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_webview, container, false);
-        //mBinding.webview.getSettings().setJavaScriptEnabled(true);
        mBinding.webview.loadUrl(mUrl);
        mBinding.webview.setWebViewClient(new CustomWebviewClient(this));
        mLoadService = LoadSir.getDefault().register(mBinding.smartrefreshlayout, new Callback.OnReloadListener() {
            @Override
            public void onReload(View v) {
                mLoadService.showCallback(LoadingCallback.class);
                mBinding.webview.reload();
            }
        });

        mBinding.smartrefreshlayout.setOnRefreshListener(this);
        mBinding.smartrefreshlayout.setEnableRefresh(mCanNativeRefresh);
        mBinding.smartrefreshlayout.setEnableLoadMore(false);

        mBinding.webview.setWebChromeClient(new CustomWebChromeClient(this));
+        WebViewDefaultSettings.getInstance().setSettings(mBinding.webview);
       // return mBinding.getRoot();
        return mLoadService.getLoadLayout();
    }

需添加权限配置

  
    

为了使应用更可靠,使得当webView即使有问题也不影响app进程,故跨进程方案设置android:process,以activity或者service为单位(fragment宿主在Activity中不能设置为独立进程)
Android高级UI之webview架构搭建(组件化module)_第1张图片
创建assets目录并放置html文件和js文件
demo.html




    
    
    
    
    
    
    
    


调用: showToast

创建js文件用于通信
Android高级UI之webview架构搭建(组件化module)_第2张图片

日志输出工具的配置chrome log
==》CustomWebChromeClient 方法中重写onChromeMessage方法

@Override
    public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
        Log.d(TAG, consoleMessage.message());
        return super.onConsoleMessage(consoleMessage);
    }
}

与JS 通信(html+javascrip+css)——命令模式
——html文件中导入js文件
——webviewprocess文件包含所有webView相关文件
——自定义WebView(addJavaScriptInterface)
——js代码调用:takeNativeAction(自定义WebView中定义的,一个参数,与IOS统一)
——HTML中的script响应

四、主线程与webviewprocess通信

4.1 封装实现跨进程通信之openActivity
——html中添加一个跳转入口处
——对应JS中处理逻辑(命令 + 参数)
——WebView接口处理
——service连接:
——AIDL + 命令管理器
——ServiceConnection实现命令分发器
——命令接口用于扩展
——autoService获取数据迭代后取代注册

4.2 跨进程实现登录并获取返回结果

Android高级UI之webview架构搭建(组件化module)_第3张图片

你可能感兴趣的:(UI控件及样式)