android浏览器研究-APP层基本架构

浏览器探究——APP层基本架构

App层的功能主要分几块:

使用WebView的浏览器页面主体

除WebView之外的UI

页面的相关功能,如页内查找,前进,后退

设置

事件

多窗口管理

书签/历史记录

 

首先看构成主体框架的几个类

BrowserActivity

BrowserActivity继承自Activity,提供了对Browser应用生命周期的控制,事件的入口。这里的事件包括Key的事件,菜单的事件等。

BrowserActivity创建了Controller(用于控制)和UI(用于显示)这两个核心类的对象。

BrowserActivity中接收到的事件等信息都传递给Controller,由Controller来做具体的处理。这样BrowserActivity其实负责很轻松的工作,就是创建和传递。这里可以把BrowserActivity当做一个外界的信息源来看待,而把UI和Controller的组合当做真正的主体看待。

 

主界面

浏览页面的主界面由接口类UI来定义对外的接口,由UI的实现类BaseUI来实现基本的功能,由BaseUI的继承类PhoneUI和XLargeUI来分别实现Phone和Pad的特殊UI界面。

Controller中有UI的引用,UI定义的接口主要就是提供给Controller,供Controller控制UI。即Controller只能通过UI提供的这些有限的接口来控制主界面。

这样看主界面的控制并不繁琐,通过UI这个接口把界面的实现和界面的控制给分离开了。

BaseUI是实现UI接口的类。BaseUI提供了主界面的实现。这里的主界面是指浏览网页的界面,不包含书签,设置等页面。

PhoneUI和XLargeUI继承自BaseUI。他们对BaseUI的一些功能做了扩展,实际上BaseUI对一些函数做了空实现,由其继承类再做具体的实现。

BaseUI主要由两部分界面组成,一个是上面的TitleBar,另一个是下面的WebView。这里分别对应了TitleBar类与Tab类。

 android浏览器研究-APP层基本架构_第1张图片

主界面的控制

有了UI界面后,需要有相应的控制器来操作UI界面。于是抽象出了主界面的控制器UiController接口。

其他的地方就可以通过获取UiController的引用,来操作UI了。

Controller实现了UiController接口,即实现UiController具体功能的就是Controller,其他地方获取的就是Controller的引用。

BaseUi本身也有UiController的引用,用于自身做一些控制跟UI相关的操作。其实UiController定义的接口并不都是控制UI界面的,而是指跟UI相关的一批功能。

Controller继承UiController接口,本身有UI接口的引用。

BaseUI继承UI接口,本身有UiController接口的引用。

 

WebView的控制

浏览器的主体是WebView,对网页的操作都是通过WebView这个控件完成的。

WebView被Tab类给包装起来,并且把BrowserSetting说也包含进来了。BrowserSetting是一个单例类,也即只有一个BrowserSetting对象。但是每一个窗口对应一个Tab。每个Tab里会创建一个WebView,同时包含BrowserSetting的引用。用公共的BrowserSetting的设置内容来配置它自己的WebView。

对于Tab,有一个TabControl的类来管理它,这里我觉得不称为控制,称为管理更好,因为TabControl与Tab是一对多的关系,TabControl用于创建,销毁Tab,并且管理所有的Tab,排序所有的Tab,让其他模块可以获取某个Tab,至于获取到Tab后,就由相应的模块直接控制该Tab了。

而TabControl又是在Controller中创建的,由Controller 来维护,但是Controller 也提供了getTabControl()的接口,可以让其他模块获取到TabControl的引用。

 

对于WebView 的控制操作,又抽象出了WebViewController接口。WebViewController中很多接口函数都是需要传入Tab作为参数的。而实现WebViewController接口的是Controller。

这就比较容易理解为什么需要传入Tab作为参数了,因为Controller中管理的是TabControl

的对象,而TabControl是管理一组Tab的。所以如果要明确的对某一个Tab进行相关的操作,则需要通过参数传入该Tab,而Tab中又包含着WebView,所以Controller能够进一步的操作到WebView。

在Tab中又有WebViewController的引用,这样Tab也可以进一步调用到TabControl,进而与其他的Tab相互控制。

android浏览器研究-APP层基本架构_第2张图片

界面,WebView,控制器

通过以上可见,Controller即实现了UiController接口,又实现了WebViewController接口。而主页面BaseUI中又有一个当前被激活使用的Tab。BaseUI与Tab都通过Controller来控制。

这样其他的模块只要获取了Controller的引用,即可控制界面的WebView和其他的界面部分。

  

WebView的接口的使用

WebView是伴随着Tab一起创建的,Tab中管理着WebView,但是WebView的create是在Controller中,再设置给Tab,这样Tab可以剥除它的WebView,也可以重新设置WebView。

但是WebView的接口主要通过Tab来调用。

Tab中有两个WebView,一个被称为mMainView,另一个为mSubView(暂时不知道何时使用)。另外有一个BrowserSettings用于获额取当前浏览器的设置,并可以通过BrowserSettings来对全局的设置进行操作。

Tab之间又可以组建父子关系,在一个页面中通过点击一个链接,并且在新的Tab页中打开这个链接时,那么新Tab就是当前这个Tab的孩子。

WebView的回调是通过WebChromeClient和WebViewClient这两个类作为回调类来实现的。

Tab中创建这两个类的继承类对象,然后设置在其WebView上。

这样外部模块通过Tab封装的WebView接口可以调用WebView的功能,或者通过Tab获取WebView,直接操作WebView来调用WebView的功能。

WebView通过回调类来回调一些操作,这些操作通过Tab实现的回调类来把回调信息传递到外部。注意Tab是可以获取到WebViewController的,而WebViewController与UiController是同一个Controller。即UI跟WebView是通过Controller连接起来的。所以在Tab中获取到回调信息后,是可以进一步通过Controller传递出去的。


UI请求WebView功能与WebView功能回调UI

基于上诉的框架可以看以下的一个例子,看下loadUrl这个操作。

当在地址栏输入一个url时并点击回车时,会触发loadUrl这个流程。

首先看界面上,地址栏是属于TitleBar的。在layout中可以看到title_bar_nav.xml文件定义了布局。而地址栏就对应了类UrlInputView。所以事件会从这里开始触发。

这个地址栏UI布局的从外到内整体情况如下:

BaseUi->TitleBar->NavigationBarBase->UrlInputView


在对事件从内向往的处理过程中,就可以通过BaseUi找到UiController了(实际代码中在创建一些UI相关的类对象时就会把UiController传给该UI类对象,以便于以后使用。但是UiController最初是在BaseUi中获取到的)。

再根据前面所述的框架,UI找到了UiController(即Controller),然后调用UiController的处理方法,UiController的处理时,此时就不要把它再看做UiController,而是看做Controller,Controller的处理会通过TabControl找到某个具体的Tab,然后再通过Tab找到WebView,进而调用WebView的loadUrl。

经过上述流程就完成了,然后Controller再调用UI接口提供的执行进度更新的处理,即又完成了Controller对UI的控制。

通过以上可见,UI部分可以通过找到UiController,进而调用Controller的处理函数。

Controller本身既包含对UI的处理,又包含对WebView的处理,以及对Tab的管理。

而Tab也可以通过WebViewController来找到Controller,进而对UI或者其他的Tab进行处理。

这样很清晰的看到Controller是个总控制,也是个中转。

android浏览器研究-APP层基本架构_第3张图片

上面对WebView执行loadUrl之后,会收到WebView的一些回调信息,这里以onPageStarted为例。

首先回调传达到WebViewClient的onPageStarted函数中。之前提过,WebViewClient是在Tab中创建的,并且关联到Tab中的WebView中。所以回调信息首先到达Tab中。

Tab如果想把信息传达到UI中那么就必须先找到Controller。Tab中有WebViewController,WebViewController就是Controller。这样Tab找到了Controller,Controller中有UI接口的对象,那么通过UI接口提供的操作就可以传达到BaseUI中,这样进一步就可以到达具体的UI控件中了比如TitleBar和NavigationBar。

 

WebView以事件方式的回调

WebView还有一种方式是以事件的方式回调。WebView本身是继承自View的一个控件,本身又有Activity的上下文信息,这样WebView可以发起一些事件,由BrowserActivity来响应,典型的一个例子是长按网页上的一个链接或者一个图片时,会弹出一个ContentMenu。

这个过程时WebView发起了performLongClick()请求,该请求会执行ContentMenu的事件调用。

BrowserActivity中的onCreateContentMenu被调用,BrowserActivity会把事件传递给Controller,由Controller来处理,Controller会根据WebView请求的一些信息来填充ContentMenu的菜单项,同时会设置菜单项的点击事件。然后又通过UI来设置TitleBar的隐藏。

这个过程其实就是组建了一个ContentMenu,然后又对当前UI做一些处理。也就是事件从WebView发出,BrowserActivity接收响应,响应传递给Controller。Controller做为主控制,则既可以操作UI也可以操作功能,可以填充ContentMenu也可以为每个菜单项设置具体的功能函数。可见在这个过程中Controller做了很多事,负担了组织和管理和分配的工作。

android浏览器研究-APP层基本架构_第4张图片

设置的管理

每个WebView有一个WebSettings与之对应,但是浏览器作为一个整体,其所有的WebView的设置内容都相同,于是在app层统一出一个BrowserSettings的单例类。

在BrowserSettings中由一个List管理了所有的WebSettings。这个是WebSettings的管理中心。

那么WebSettings的来源呢?在创建WebView的时候,会从该WebView中取出它的WebSettings,然后把这个WebSettings加入到BrowserSettings中进行统一管理,并且还会以当前BrowserSettings中的配置情况对这个WebSettings进行同步设置,这样新的WebSettings的设置情况就跟其他的WebSettings一样了,也即新创建的WebView的设置情况与其他的WebView的设置情况统一了。这么看就跟一个新员工入职一样,新员工入职(创建WebView),进行登记(把它的WebSettings加入到BrowserSettings),并且对他进行员工配置和培训(同步它的WebSettings),这样新员工就跟其他同事有了相同的职位属性了(WebSettings配置相同)。

 

设置的本地存储

有了上述的设置的管理和同步后,这些设置还需要保存到本地,以便下次启动时同步。根据android的数据保存的方式,该配置采用SharedPreferences的形式来保存,保存的位置就是手机的/data/data/com.android.browser/shared_prefs/com.android.browser_preferences.xml中。

BrowserSettings可以获取到SharedPreferences,通过SharedPreferences来读取和写入某项设置的配置情况。并且BrowserSettings把自身作为OnSharedPreferenceChangeListener注册给SharedPreferences,这样当SharedPreferences有变化时,BrowserSettings会请求同步所有的WebSettings,这样各个WebSettings始终跟SharedPreferences的配置情况保持一致。


设置的UI

设置的UI采用PreferenceActivity的方式,先把设置分组,每组作为一个header,见preference_headers.xml

每组的页面又以PreferenceFragment的形式展现,各个PreferenceFragment的初始配置从SharedPreferences中对应项取出。

当用户选择一些配置项的设置时,就会触发前面所说的SharedPreferences的更新事件,对于一些复杂的配置项,则需要在PreferenceFragment中主动的执行SharedPreferences的设置了,这样同样也会触发SharedPreferences的更新事件。

 android浏览器研究-APP层基本架构_第5张图片

设置的整体结构

这样,把上述的内容组合起来得到下面的设置的整体结构

 android浏览器研究-APP层基本架构_第6张图片

你可能感兴趣的:(android,浏览器,架构,APP)