Android Browser App 源码分析(三)之UI篇第一讲

Android Native Browser的界面还是比较单一,比较少的。主要体现为:主界面(主要用于加载网页)、设置页面(用于设置浏览器中各个属性,比如是否启用JavaScript、是否保存密码等)、书签&历史记录页面(展示书签以及访问网页的历史记录)。

首先从代码层面分析下主界面的UI逻辑实现,看看到底是如何加载网页的。

(一)基础架构

Browser定义了UI接口来统管整个主界面的操作,以及对Activity生命周期发生变化的处理。
因Browser App同时也要兼容平板设备,所以,这里又抽象出一个抽象类BaseUi来实现手机与平板公共通用的部分,然后将差异性的方法通过派生类PhoneUi与XLargeUi来实现。

Browser主界面头部会有一个标题栏,主要用于输入网址、保存书签,因为平板与手机的尺寸是不同的,对应的头部Tab页导航展示也就不同了,所以Browser内部又声明了NavigationBarPhone、NavigationBarTablet类来进行处理,他们继承于NavigationBarBase类。

整个结构关系如下:

《Android Browser App 源码分析(三)之UI篇第一讲》

(二)主界面如何Load出来的

启动页:BrowserActivity::onCreate()
初始化Controller 对象

然后调用Controller start方法

然后调用CrashRecoveryHandler startRecovery方法

CrashRecoveryHandler实例的初始化调用在Controller构造函数中:
mCrashRecoveryHandler = CrashRecoveryHandler.initialize(this); //实例化CrashRecoveryHandler对象,CrashRecoveryHandler构造函数中同时又创建了foregroundHandler和backgroundHandler

mCrashRecoveryHandler.preloadCrashState();
//mBackgroundHandler.sendEmptyMessage(MSG_PRELOAD_STATE); 
调用loadCrashState,从STATE_FILE(browser_state.parcel)文件中读入到mRecoveryState中

调用mController.doStart(mRecoveryState, intent); 将mRecoveryState传递过去

然后对mRecoveryState中的lastActiveDate进行判断,如果最后一次浏览器的使用时间在24小时内,否则的话销毁所有剩余的隐身标签页。

调用mTabControl.canRestoreState来获取TabId
如果等于-1,执行CookieManager.getInstance().removeSessionCookie()

然后调用GoogleAccountLogin.startLoginIfNeeded进行登录
如果已经登录或者没有找到账号,直接执行runnable.run 方法
否则执行登录操作

onPreloginFinished 方法:
如果tabId等于-1(默认的情况下第一次进来为-1):
如果intent为null:调用openTabToHomePage方法,打开主页
如果intent不为null:获取urlData,如果为空:调用openTabToHomePage方法,打开主页
否则打开Tab,加载对应的urlData

调用openTabToHomePage:
openTab(mSettings.getHomePage(), false, true, false);

最终会调用这个openTab(String url, boolean incognito, boolean setActive,boolean useCurrent, Tab parent)方法:

通过createNewTab创建一个Tab对象
内部是通过TabControl.createNewTab来进行创建
createNewTab(boolean privateBrowsing)—> createNewTab(Bundle state, boolean privateBrowsing) —->  createNewWebView实例化WebView对象—> mController.getWebViewFactory().createWebView(privateBrowsing)
—-> BrowserWebViewFactory.createWebView 创建WebView
—–> instantiateWebView、initWebViewSettings

WebView创建完毕之后,开始实例化一个Tab对象,并添加到mTabs集合中:
Tab t = new Tab(mController, w, state);
mTabs.add(t);

调用Controller.onSetWebView —> mUi.onSetWebView(tab, view);
—–>BaseUi.onSetWebView

然后container = mActivity.getLayoutInflater().inflate(R.layout.tab, mContentView, false); 创建装载WebView的Tab容器



之后调用  t.putInBackground(); 先把标签放入后台

调用addTab()–>mUi.addTab 将tab传递到对应的UI中
这个方法PhoneUi没有重写,XLargeUi重写了。

然后调用 Controller.setActiveTab(tab) —>  mTabControl.setCurrentTab(tab)、mUi.setActiveTab(tab)

—>PhoneUi::setActiveTab

—>BaseUi::setActiveTab

—>attachTabToContentView(tab)

protected void attachTabToContentView(Tab tab) {
        if ((tab == null) || (tab.getWebView() == null)) {
            return;
        }
        View container = tab.getViewContainer();
        WebView mainView  = tab.getWebView();
        // Attach the WebView to the container and then attach the
        // container to the content view.
        FrameLayout wrapper =
                (FrameLayout) container.findViewById(R.id.webview_wrapper);
        ViewGroup parent = (ViewGroup) mainView.getParent();
        if (parent != wrapper) {
            if (parent != null) {
                parent.removeView(mainView);
            }
            wrapper.addView(mainView);
        }
        parent = (ViewGroup) container.getParent();
        if (parent != mContentView) {
            if (parent != null) {
                parent.removeView(container);
            }
            mContentView.addView(container, COVER_SCREEN_PARAMS);
        }
        mUiController.attachSubWindow(tab);
    }

获取Tab的ViewContainer,获取container中的webview_wrapper控件,然后将tab对应的webView添加到其中,然后再将container添加到mContentView中

那mContentView是从哪里来的呢?

是通过实例化PhoneUi对象来的,在BaseUi构造函数中;

FrameLayout frameLayout = (FrameLayout) mActivity.getWindow()
    .getDecorView().findViewById(android.R.id.content);
LayoutInflater.from(mActivity)
    .inflate(R.layout.custom_screen, frameLayout);
mContentView = (FrameLayout) frameLayout.findViewById(R.id.main_content);

然后调用loadUrl来加载url

loadUrl(Tab tab, String url)–>loadUrl(Tab tab, String url, Map<String, String> headers)

if (tab != null) {
    dismissSubWindow(tab);
    tab.loadUrl(url, headers);
    mUi.onProgressChanged(tab);
}

Tab.java:

public void loadUrl(String url, Map<String, String> headers) {
    if (mMainView != null) {
        mPageLoadProgress = INITIAL_PROGRESS;
        mInPageLoad = true;
        mCurrentState = new PageState(mContext, false, url, null);
        mWebViewController.onPageStarted(this, mMainView, null);
        mMainView.loadUrl(url, headers);
    }
}



最终执行mMainView loadUrl方法加载url,显示对应url的网页。

    原文作者:Android源码分析
    原文地址: https://blog.csdn.net/asdf812225572/article/details/53996277
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞