webview创建过程分析(一)

22 篇文章 0 订阅

我们知道在使用webview的时候需要先创建一个weview,即

WebView webView = new WebView(context)
今天我们通过源码来分析这个WebView的创建过程。当我们使用上面的代码创建webview之后,会调用到下面WebView的构造方法中,这里除了context参数之后其他的都是默认值

protected WebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes,
            Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) {
        super(context, attrs, defStyleAttr, defStyleRes);
 
        // WebView is important by default, unless app developer overrode attribute.
        if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
            setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
        }
 
        if (context == null) {
            throw new IllegalArgumentException("Invalid context argument");
        }
        sEnforceThreadChecking = context.getApplicationInfo().targetSdkVersion >=
                Build.VERSION_CODES.JELLY_BEAN_MR2;
 
        //1.线程检查
        checkThread();
 
        //2.创建WebViewProvider
        ensureProviderCreated();
 
        //3.初始化WebViewProvider
        mProvider.init(javaScriptInterfaces, privateBrowsing);
        // Post condition of creating a webview is the CookieSyncManager.getInstance() is allowed.
        CookieSyncManager.setGetInstanceIsAllowed();
    }

从上面的创建过程可以知道这里主要分3步

进行线程检查
初始化WebViewProvider
初始化这个provider。
接下来我们仔细分析下第二和第三步

创建WebViewProvider
我们看下创建WebViewProvider的源码过程,也就是WebView中ensureProviderCreated()方法

private void ensureProviderCreated() {
        checkThread();
        if (mProvider == null) {
            // As this can get called during the base class constructor chain, pass the minimum
            // number of dependencies here; the rest are deferred to init().
 
            //主要过程分为两步
            //1.getFactory
            //2.createWebView
            mProvider = getFactory().createWebView(this, new PrivateAccess());
        }
    }
private static WebViewFactoryProvider getFactory() {
        return WebViewFactory.getProvider();
    }
这里会调用WebViewFactory 的getProvider方法:

getProvider
static WebViewFactoryProvider getProvider() {
         synchronized (sProviderLock) {
             // For now the main purpose of this function (and the factory abstraction) is to keep
             // us honest and minimize usage of WebView internals when binding the proxy.
             if (sProviderInstance != null) return sProviderInstance;
 
             final int uid = android.os.Process.myUid();
             if (uid == android.os.Process.ROOT_UID || uid == android.os.Process.SYSTEM_UID
                     || uid == android.os.Process.PHONE_UID || uid == android.os.Process.NFC_UID
                     || uid == android.os.Process.BLUETOOTH_UID) {
                throw new UnsupportedOperationException(
                        "For security reasons, WebView is not allowed in privileged processes");
            }
 
            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
            Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getProvider()");
            try {
 
                1.获取providerClass类
                Class<WebViewFactoryProvider> providerClass = getProviderClass();
                Method staticFactory = null;
                try {
                    2.获取“create”方法名
                    staticFactory = providerClass.getMethod(
                        CHROMIUM_WEBVIEW_FACTORY_METHOD, WebViewDelegate.class);
                } catch (Exception e) {
                    if (DEBUG) {
                        Log.w(LOGTAG, "error instantiating provider with static factory method", e);
                    }
                }
 
                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactoryProvider invocation");
                try {
                    3.创建provider实例
                    sProviderInstance = (WebViewFactoryProvider)
                            staticFactory.invoke(null, new WebViewDelegate());
                    if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance);
                    return sProviderInstance;
                } catch (Exception e) {
                    Log.e(LOGTAG, "error instantiating provider", e);
                    throw new AndroidRuntimeException(e);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                }
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                StrictMode.setThreadPolicy(oldPolicy);
           }
        }
    }

我们把getProvider的执行过程主要分为3个步骤

获取providerClass类
获取“create”方法名
创建provider实例
下面分别看下这几个步骤的实现

获取providerClass类
 private static Class<WebViewFactoryProvider> getProviderClass() {
         Context webViewContext = null;
         Application initialApplication = AppGlobals.getInitialApplication();
 
         try {
             Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW,
                     "WebViewFactory.getWebViewContextAndSetProvider()");
             try {
                 webViewContext = getWebViewContextAndSetProvider();
            } finally {
                 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
             }
             Log.i(LOGTAG, "Loading " + sPackageInfo.packageName + " version " +
                     sPackageInfo.versionName + " (code " + sPackageInfo.versionCode + ")");
 
             Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getChromiumProviderClass()");
            try {
                 initialApplication.getAssets().addAssetPathAsSharedLibrary(
                         webViewContext.getApplicationInfo().sourceDir);
                ClassLoader clazzLoader = webViewContext.getClassLoader();
 
                 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
 
                 1.loadNativeLibrary
                 loadNativeLibrary(clazzLoader, sPackageInfo);
                 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
 
                 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()");
                 try {
                     2.获取provider类型
                     return getWebViewProviderClass(clazzLoader);
                 } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                 }
             } catch (ClassNotFoundException e) {
                Log.e(LOGTAG, "error loading provider", e);
                 throw new AndroidRuntimeException(e);
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
             }
         } catch (MissingWebViewPackageException e) {
             // If the package doesn't exist, then try loading the null WebView instead.
            // If that succeeds, then this is a device without WebView support; if it fails then
             // swallow the failure, complain that the real WebView is missing and rethrow the
            // original exception.
             try {
                 return (Class<WebViewFactoryProvider>) Class.forName(NULL_WEBVIEW_FACTORY);
             } catch (ClassNotFoundException e2) {
                 // Ignore.
             }
             Log.e(LOGTAG, "Chromium WebView package does not exist", e);
             throw new AndroidRuntimeException(e);
         }
     }

整个getProviderClass过程中会先加载chromium 的so,然后通过getWebViewProviderClass获取provider的类型,我们看下getWebViewProviderClass的实现过程

getWebViewProviderClass
public static Class<WebViewFactoryProvider> getWebViewProviderClass(ClassLoader clazzLoader)
             throws ClassNotFoundException {
         return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY,
                 true, clazzLoader);
     }
 
 
//不同版本会有不同的值
private static final String CHROMIUM_WEBVIEW_FACTORY =
63            "com.android.webview.chromium.WebViewChromiumFactoryProviderForO"
 从上面的逻辑可以看到,不同版本会有不同的WebViewFactoryProvider类。

从ensureProviderCreated可以知道要创建WebViewProvider需要两步,第一创建WebViewFactoryProvider,第二步调用WebViewFactoryProvider的createWebView方法创建WebViewProvider。

从上面的源码可以知道WebViewFactoryProvider的创建主要是通过反射来创建的,而创建的实例是WebViewChromiumFactoryProviderForOMR1的对象。接下来我们看下这个类

 
class WebViewChromiumFactoryProviderForOMR1 extends WebViewChromiumFactoryProvider {
    public static WebViewChromiumFactoryProvider create(android.webkit.WebViewDelegate delegate) {
        return new WebViewChromiumFactoryProviderForOMR1(delegate);
    }
    protected WebViewChromiumFactoryProviderForOMR1(android.webkit.WebViewDelegate delegate) {
        super(delegate);
    }
}
WebViewChromiumFactoryProviderForOMR1这个类其实很简单,它继承WebViewChromiumFactoryProvider,主要的功能也是在父类中实现的,WebViewChromiumFactoryProviderForOMR1这个本身更像是一个跟随版本变化的一个webview框架跟chromium之间的一个桥梁。

从上面的代码可以知道在ensureProviderCreated这里得到的WebViewFactoryProvider其实是一个WebViewChromiumFactoryProvider。

有了WebViewChromiumFactoryProvider类名之后我们在回到 getProvider的步骤中,看下获取create方法名

获取“create”方法名
private static final String CHROMIUM_WEBVIEW_FACTORY_METHOD = "create";
。。。。。。
try {
                    2.获取“create”方法名
                    staticFactory = providerClass.getMethod(
                        CHROMIUM_WEBVIEW_FACTORY_METHOD, WebViewDelegate.class);
                } catch (Exception e) {
                    if (DEBUG) {
                        Log.w(LOGTAG, "error instantiating provider with static factory method", e);
                    }
                }
。。。。。。。
从这里可以看出调用的方法名create方法,方法的参数类型是WebViewDelegate

再接着看getProvider的步骤

创建provider实例
。。。。。。。
try {
                    3.创建provider实例
                    sProviderInstance = (WebViewFactoryProvider)
                            staticFactory.invoke(null, new WebViewDelegate());
                    if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance);
                    return sProviderInstance;
                } catch (Exception e) {
                    Log.e(LOGTAG, "error instantiating provider", e);
                    throw new AndroidRuntimeException(e);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                }
。。。。。。。。
这里会先new 一个WebViewDelegate对象,然后执行create方法来得到一个WebViewFactoryProvider对象 。

有了WebViewFactoryProvider之后就可以用来创建WebViewProvider了。

public WebViewProvider createWebView(WebView webView, WebView.PrivateAccess privateAccess) {
        return new WebViewChromium(this, webView, privateAccess, mShouldDisableThreadChecking);
    }
从上面的代码可以知道这里最终创建WebViewProvider的是一个WebViewChromium对象

有了WebViewChromium之后就调用它的init方法

小结一下:

在webview的创建过程中会创建WebViewChormiumFactoryProvider和WebViewChromium对象。至于WebViewChormiumFactoryProvider和WebViewChromium的初始化过程以及WebViewChromium的init方法中执行了何种操作,我们在下一篇文章中进行分析
————————————————

原文链接:https://blog.csdn.net/andyhxc/article/details/89453359

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值