一、架构搭建

首先,我们确定第一步应该完成什么:

作为封装,一个抽象的父类是必须要的,比如初始化webView,webView的生命周期管理,因为大家知道webView容易内存泄漏。我们建立一个抽象类WebDelegate.java继承自fragment。

同时,子类实现一些具体的做法,比如webSettings的设置。

既然如此,父类就应当和子类通信,因为有些webView的设置必须在子类实现,而这些设置,应该在父类初始化webView的时候就执行。很明显,我们需要一个接口类,进行回调通信。我们建立一个接口类IWebViewInitializer。

子类通过继承获取父类数据,而父类通过接口回调获得数据。关系图:

初步架构通信图

二、IWebViewInitializer回调接口

我们想让子类必须实现这个接口,注意是必须,若非必须可参考onClick点击事件的设计,而由于这里是必须实现,所以我们先在WebDelegate基类中创建抽象方法:

public abstract IWebViewInitializer setInitializer();

因此,父类已经可以获取到我们的接口实例了。具体接口如下:

public interface IWebViewInitializer {

WebView initWebViewSettings(WebView webView);

//针对浏览器本身行为的控制,如前进后退的回调

WebViewClient initWebViewClient();

//针对页面的控制,如js交互

WebChromeClient initWebChromeClient();

}

子类需要实现3个具体的方法,具体实现以后再谈,我们先考虑父类。

三、父类WebDelegate

3.1 继承自fragment,首先定义一些变量,其中:

为了弱引用创建了一个引用队列

使用布尔变量mIsWebViewAvailable,这里是参考sdk里自带的WebViewFragment类(api25及其以下才有),这个类是为了显示一个WebView,而用一个布尔变量,能让webView在fragment pause或者resume的时候自动也跟着pause和resume(原理很简单的)

private WebView mWebView = null;

private final ReferenceQueue WEB_VIEW_QUEUE = new ReferenceQueue<>();

private String mUrl = null;

private boolean mIsWebViewAvailable = false;

3.2 初始化WebView

初始化工作,此方法在onCreate()中执行:

注意初始化的时候使用了 弱引用防止内存泄漏

初始化后mIsWebViewAvailable变为true表示之后webview可用了

addJavascriptInterface方法会让网页里的js能调用本地LatteWebInterface实例里的方法,此类在章节4里写

@SuppressLint("JavascriptInterface")

private void initWebView() {

if(mWebView !=null){

mWebView.removeAllViews();

mWebView.destroy();

}else {

//获取子类回调传回来的接口实例

final IWebViewInitializer initializer = setInitializer();

if(initializer !=null){

final WeakReference webViewWeakReference =

new WeakReference(new WebView(getContext()),WEB_VIEW_QUEUE);

mWebView = webViewWeakReference.get();

mWebView = initializer.initWebViewSettings(mWebView);

mWebView.setWebViewClient(initializer.initWebViewClient());

mWebView.setWebChromeClient(initializer.initWebChromeClient());

//为webView添加js接口对象映射,让网页上的js能调用本地代码,注意此方法要加注解

mWebView.addJavascriptInterface(LatteWebInterface.create(this),"latte");

//webview可用了

mIsWebViewAvailable = true;

}else {

throw new NullPointerException("Initializer is null!");

}

}

}

主要的初始化完毕后,其次是在一些回调事件(比如onPause)中处理webView的生命周期,防止内存泄漏,完整的基类暂时如下:

/**

* @function 网络服务的抽象基类

* Created by 尤晟 on 2017-07-29.

*/

//这里继承的BaseDelegate基类暂时理解为封装过的Fragment,第二篇中会有详细封装过程

public abstract class WebDelegate extends BaseDelegate{

private WebView mWebView = null;

private final ReferenceQueue WEB_VIEW_QUEUE = new ReferenceQueue<>();

private String mUrl = null;

private boolean mIsWebViewAvailable = false;

public WebDelegate() {

}

public abstract IWebViewInitializer setInitializer();

@Override

public void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

final Bundle args = getArguments();

mUrl = args.getString(RouteKeys.URL.name());

initWebView();

}

//初始化webview

@SuppressLint("JavascriptInterface")

private void initWebView() {

if(mWebView !=null){

mWebView.removeAllViews();

mWebView.destroy();

}else {

final IWebViewInitializer initializer = setInitializer();

if(initializer !=null){

final WeakReference webViewWeakReference =

new WeakReference(new WebView(getContext()),WEB_VIEW_QUEUE);

mWebView = webViewWeakReference.get();

mWebView = initializer.initWebViewSettings(mWebView);

mWebView.setWebViewClient(initializer.initWebViewClient());

mWebView.setWebChromeClient(initializer.initWebChromeClient());

mWebView.addJavascriptInterface(LatteWebInterface.create(this),"latte");

//webview可用了

mIsWebViewAvailable = true;

}else {

throw new NullPointerException("Initializer is null!");

}

}

}

public WebView getWebView() {

if (mWebView == null) {

throw new NullPointerException("WebView IS NULL!");

}

return mIsWebViewAvailable ? mWebView : null;

}

public String getUrl() {

if (mUrl == null) {

throw new NullPointerException("WebView IS NULL!");

}

return mUrl;

}

@Override

public void onPause() {

super.onPause();

if(mWebView !=null){

mWebView.onPause();

}

}

@Override

public void onResume() {

super.onResume();

if (mWebView != null) {

mWebView.onResume();

}

}

@Override

public void onDestroyView() {

super.onDestroyView();

mIsWebViewAvailable = false;

}

@Override

public void onDestroy() {

super.onDestroy();

if (mWebView != null) {

mWebView.removeAllViews();

mWebView.destroy();

mWebView = null;

}

}

}

四、创建js交互的本地对象类LatteWebInterface

此类在父基类WebDelegate中的addJavascriptInterface方法中就被调用,进行对象映射,为了让js代码执行此类中的方法。

/**

* @function 用来和原生进行交互,js代码中通过反射调用此类中的方法

* Created by 尤晟 on 2017-07-30.

*/

public class LatteWebInterface {

private final WebDelegate DELEGATE;

private LatteWebInterface(WebDelegate DELEGATE) {

this.DELEGATE = DELEGATE;

}

//简单工厂模式

static LatteWebInterface create(WebDelegate delegate){

return new LatteWebInterface(delegate);

}

//js中会调用此方法

public String event(String params) {

final String action = JSON.parseObject(params).getString("data");

return null;

}

}

五、总结

至此,基类,子类的回调接口,js本地类三个文件已暂时编写完成,已可以初步使用,但是还远远不够,后续篇目中将继续封装,可关注本人~~

android webview 基类,Android开罐头——WebView高可扩展性封装(一)相关推荐

  1. android webview 类,Android开罐头——WebView高可扩展性封装(二)

    一.回顾与规划 回顾一下,我们在第一章中已经完成了一些封装: 我们看一下我们的目前的架构图片: 初步架构通信图 我们已经实现了: 抽象父类WebDelegate,用来管理webView的生命周期,以及 ...

  2. android mvp框架基类,Android MVP架构项目搭建封装,基类封装

    综述 对于MVP (Model View Presenter)架构是从著名的MVC(Model View Controller)架构演变而来的.而对于Android应用的开发中本身可视为一种MVC架构 ...

  3. android 基类fragment,Android DialogFragment 基类的定制

    鸿洋博客介绍:DialogFragment的基本使用 好处: 1:使用DialogFragment来管理对话框,当旋转屏幕和按下后退键时可以更好的管理其声明周期,它和Fragment有着基本一致的生命 ...

  4. android sharedpreferences 工具类,android sharedpreferences工具类

    释放双眼,带上耳机,听听看~! 今天,简单讲讲如何写一个sharedpreferences的工具类. 很简单,把一些重复的操作封装在工具类里,其他地方调用就可以.在网上搜索了比较多的资料,找到一个比较 ...

  5. Android加密工具类,Android AES加密工具类分享

    1.AES加密工具类 java不支持PKCS7Padding,只支持PKCS5Padding.我们知道加密算法由算法+模式+填充组成,下一篇介绍iOS和Android通用的AES加密,本篇文章使用PK ...

  6. android attributeset 工具类,Android使用AttributeSet自定义控件的方法

    释放双眼,带上耳机,听听看~! 所谓自定义控件(或称组件)也就是编写自己的控件类型,而非Android中提供的标准的控件,如TextView,CheckBox等等.不过自定义的控件一般也都是从标准控件 ...

  7. android attributeset 工具类,android – 如何将AttributeSet传递给自定义视图

    如何将当前的AttributeSet传递给自定义View类?如果我使用的参数中只有Context的构造函数,我将丢失所有主题,并在该自定义视图的xml中使用"style"标签的能力 ...

  8. android dp工具类,Android 单位px、dp、sp转换工具类

    import android.content.Context; import android.util.TypedValue; //常用单位转换的辅助类 public DensityUtils { p ...

  9. android 计时器工具类,Android中通用定时器--好用的工具

    package com.utility.common; import android.os.Handler; import android.os.Message; public class BaseT ...

最新文章

  1. mysql signed 长度_浅谈mysql字段长度设置
  2. Matlab解析LQR与MPC的关系
  3. Ubuntu安装teamviewer
  4. 动态路由之RIP协议、Bellman-Ford算法
  5. charles抓包https/模拟弱网/设置断点/修改接口请求值或返回值/压测
  6. 《数据结构题集》2.12
  7. 关于代码家(干货集中营)共享知识点汇总系列——休息娱乐
  8. 测试开发面试题(一)-----appium相关
  9. 浅析内网沟通软件有什么特点
  10. 触摸屏设置禁用手指缩放机双击放大功能
  11. 推荐4个方便实用的软件神器,非常适合程序员
  12. DBF文件格式及读写实践
  13. 用贾樟柯访谈评《疯狂的程序员》
  14. 微信朋友圈图片显示缩放
  15. 移动路由器做网站服务器,移动路由器上网方式选哪个?
  16. 2019 ICPC 南京 F题 Paper Grading
  17. wke播放优酷提示客户端权限的问题
  18. STC89C52电子时钟
  19. 秀智商,答对12题平分百万-《百万英雄》
  20. apple store 爬虫

热门文章

  1. Java模拟银行账户简单的存取款、余额查询操作。
  2. Linux安装Oracle数据库
  3. Oracle数据库恢复表和表数据
  4. OleDbParameter参数的使用
  5. 单页(SPA)首页白屏优化
  6. 若依框架模块名称修改
  7. Docker kill 1无效
  8. 批处理 IF-ERRORLEVEL使用方法
  9. 在react中使用css modules解决组件之间样式覆盖问题
  10. ldd命令 ubuntu_技术|简单介绍 ldd 命令