WebView相关问题
WebView相关问题
WebView 的内核
WebView 内核加载逻辑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_32 =
"/data/misc/shared_relro/libwebviewchromium32.relro";
private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_64 =
"/data/misc/shared_relro/libwebviewchromium64.relro";
/**
* Load WebView's native library into the current process.
*
* <p class="note"><b>Note:</b> Assumes that we have waited for relro creation.
*
* @param clazzLoader class loader used to find the linker namespace to load the library into.
* @param libraryFileName the filename of the library to load.
*/
public static int loadNativeLibrary(ClassLoader clazzLoader, String libraryFileName) {
if (!sAddressSpaceReserved) {
Log.e(LOGTAG, "can't load with relro file; address space not reserved");
return WebViewFactory.LIBLOAD_ADDRESS_SPACE_NOT_RESERVED;
}
String relroPath = VMRuntime.getRuntime().is64Bit() ? CHROMIUM_WEBVIEW_NATIVE_RELRO_64 :
CHROMIUM_WEBVIEW_NATIVE_RELRO_32;
int result = nativeLoadWithRelroFile(libraryFileName, relroPath, clazzLoader);
if (result != WebViewFactory.LIBLOAD_SUCCESS) {
Log.w(LOGTAG, "failed to load with relro file, proceeding without");
} else if (DEBUG) {
Log.v(LOGTAG, "loaded with relro file");
}
return result;
}
Android 免安装升级 WebView 内核
WebView 存在什么问题?及怎么解决?
WebView 崩溃?
WebView 的优化
WebView 预加载
WebView 多进程
WebView 资源存本地
通用拦截 - 缓存共享、请求并行 直出解决了文字展现的速度问题,但是图片加载渲染速度还不理想。 借由内核的 shouldInterceptRequest 回调,拦截落地页图片请求,由客户端调用图片下载框架进行下载,并以管道方式填充到内核的 WebResourceResponse 中。就是说在 shouldInterceptRequest 拦截所有 URL,之后只针对后缀是.PNG/.JPG 等图片资源,使用第三方图片下载工具类似于 Fresco 进行下载并返回一个 InputStream。
WebView 秒开(WebView 白屏)
网页加载缓慢,白屏,使用卡顿。
为何有这种问题?
- 调用 loadUrl() 方法的时候,才会开始网页加载流程
- js 臃肿问题
- 加载图片太多
- webview 本身问题
白屏问题如何监控?
什么时候会出现白屏?
- 资源加载错误:尤其是 JS 资源加载异常时
- 页面逻辑问题
- 读取 undefined null 的属性,
null.a;
- 对普通对象进行函数调用,
const o = {}; o();
- 将 null undefined 传递给 Objects.keys,
Object.keys(null);
- JSON 反序列化接受到非法值,
JSON.parse({});
- 接口异常导致的白屏:页面数据依赖网络接口,且页面没有默认的初始数据,导致在网络不好的情况下,接口数据没有获取到,从而导致页面列表数据空白等问题。
如何判断是否白屏?
判断屏幕元素是否为白屏元素
Webiew 是怎么加载网页的呢?
Webview 初始化→DOM 下载→DOM 解析→CSS 请求/下载→CSS 解析→渲染→绘制→合成
优化方向
1、提前内核初始化
1
2
3
4
5
6
7
8
public class App extends Application {
private WebView mWebView ;
@Override
public void onCreate() {
super.onCreate();
mWebView = new WebView(new MutableContextWrapper(this));
}
}
2、Webview 复用池
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public class WebPools {
private final Queue<WebView> mWebViews;
private Object lock = new Object();
private static WebPools mWebPools = null;
private static final AtomicReference<WebPools> mAtomicReference = new AtomicReference<>();
private static final String TAG=WebPools.class.getSimpleName();
private WebPools() {
mWebViews = new LinkedBlockingQueue<>();
}
public static WebPools getInstance() {
for (; ; ) {
if (mWebPools != null)
return mWebPools;
if (mAtomicReference.compareAndSet(null, new WebPools()))
return mWebPools=mAtomicReference.get();
}
}
public void recycle(WebView webView) {
recycleInternal(webView);
}
public WebView acquireWebView(Activity activity) {
return acquireWebViewInternal(activity);
}
private WebView acquireWebViewInternal(Activity activity) {
WebView mWebView = mWebViews.poll();
LogUtils.i(TAG,"acquireWebViewInternal webview:"+mWebView);
if (mWebView == null) {
synchronized (lock) {
return new WebView(new MutableContextWrapper(activity));
}
} else {
MutableContextWrapper mMutableContextWrapper = (MutableContextWrapper) mWebView.getContext();
mMutableContextWrapper.setBaseContext(activity);
return mWebView;
}
}
private void recycleInternal(WebView webView) {
try {
if (webView.getContext() instanceof MutableContextWrapper) {
MutableContextWrapper mContext = (MutableContextWrapper) webView.getContext();
mContext.setBaseContext(mContext.getApplicationContext());
LogUtils.i(TAG,"enqueue webview:"+webView);
mWebViews.offer(webView);
}
if(webView.getContext() instanceof Activity){
//throw new RuntimeException("leaked");
LogUtils.i(TAG,"Abandon this webview , It will cause leak if enqueue !");
}
}catch (Exception e){
e.printStackTrace();
}
}
}
带来的问题:内存泄漏
3、独立进程,进程预加载
启动 webview 页面前,先启动 PreWebService 把 web 进程创建了,当启动 WebActivity 时,系统发发现 web 进程已经存在了,就不需要花费时间 Fork 出新的 web 进程了。
4、使用 x5 内核,替换原生的浏览器内核
5、app 内置资源
app 内置 css、js 文件并控制版本
6、三方框架和大厂方案
VasSonic VasSonic 的核心思想: 并行,充分利用 webview 初始化的时间进行一些数据的处理。在包含 webview 的 activity 启动时会一边进行 webview 的初始化逻辑,一边并行的执行 sonic 的逻辑。这个 sonic 逻辑就是网页的预加载
- 百度 app 方案
- 今日头条方案
本文由作者按照 CC BY 4.0 进行授权