最近一个小伙伴用腾讯X5时总是出错,所以有了这篇文章,就像标题写的,你的WebView的使用及创建,一定要在腾讯X5初始化完成之后。
说下他的场景,MainActivity直接就打开X5WebView 去加载网页。导致使用的是原生WebView。
http://res.imtt.qq.com/TES/x5%20api%20-simple_1493283262924.pdf
但是,很重要一点,如果我们按照官方Demo的写法,Application中去初始化X5内核的时候,初始化的过程是在子线程中进行的,回调是主线程回调的。
源码简单分析一波
首先我们想一下,回调onViewInitFinished()函数肯定是在 initX5Environment() 这个函数 内被回调的,那么如果initX5Environment() 内所有函数均是主线程中运行,那么就不会出现 官方文档说的 我们使用的 WebView要在回调之后使用了。
所以在initX5Environment()这个函数内部一定有子线程。
先看 h 类
函数名称 onInstallFinish 函数名就表达了一切,接着看 preInit
有 MainLooper()所以 f 应该就是 handler,看内部回调,没问题,我们接着看 g 类
g 是个线程,那么我们就可以得出结论,开启工作线程,工作线程使用MainLooper,初始化完成就使用 handler 发送消息,进行回调。
这里关于使用MainLooper多说一句
举个例子
如果我在子线程创建了 handler,并重写了HandlerMessage,然后Hanlder使用的是MainLooper,这时候我在子线程使用handler发送了一个消息,那么这个消息处理是主线程处理还是子线程处理????
当然是主线程
这个就涉及handler.sendMessage 和 Looper.loop 函数
步骤:
子线程handler:workHandler
子线程发送的Message:workMsg
1、workHandler.sendMessage(workMsg) ,经过一步一步,最终放到了 MainLooper内的MessageQueue中
2、由于主线程开启了Looper.loop,这时候Looper 取出 workMsg,记住这一点,是主线程中的函数 Looper.loop取出了workMsg。
3、那取出的这个 workMsg给谁去处理呢??
4、workMsg中有个属性 workMsg.target,这个 workMsg.target 就是 workHandler
5、然后回调 workHandler 的 callBack 或者 handleMessage
最后附上一个案例
package com.chinabim.myapplication; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; /** * @author 高延荣 * @date 2018/3/1 10:47 * 描述: */ public class MainActivity extends AppCompatActivity { private static final String TAG = "MainLooper测试"; private Handler handler1; private Handler handler2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Thread thread1 = new Thread(new Runnable() { @Override public void run() { handler1 = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { Log.i(TAG, Thread.currentThread().getName()); } }; } }, "我是第一个子线程"); Thread thread2 = new Thread(new Runnable() { @Override public void run() { handler2 = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { Log.i(TAG, Thread.currentThread().getName()); } }; } }, "我是第二个子线程"); thread1.start(); thread2.start(); try { Thread.sleep(3 * 1000L); } catch (InterruptedException e) { e.printStackTrace(); } handler1.sendEmptyMessage(1); handler2.sendEmptyMessage(2); } }
谢谢大家的观看