讲解PhoneGap的底层原理,需要从讲解PhoneGap几个重要的类开始:
DroidGap类:
public class DroidGap extends Activity implements CordovaInterface {...}
DroidGap是接口CordovaInterface的实现类,继承Android Activity,具有Android Activity的整个生命周期。DroidGap覆写了Activity的 onCreate()、onPause()、onResume()、onDestroy
等方法。
1 /** 2 * Load the url into the webview. 3 * 4 * @param url 5 */ 6 public void loadUrl(String url) { 7 8 // Init web view if not already done 9 if (this.appView == null) { 10 this.init(); 11 } 12 13 // Set backgroundColor 14 this.backgroundColor = this.getIntegerProperty("backgroundColor", Color.BLACK); 15 this.root.setBackgroundColor(this.backgroundColor); 16 17 // If keepRunning 18 this.keepRunning = this.getBooleanProperty("keepRunning", true); 19 20 // Then load the spinner 21 this.loadSpinner(); 22 23 this.appView.loadUrl(url); 24 }
其中有一个比较重要的方法是loadUrl(String url),也就是在你的Activity里super.loadUrl()时调用的方法。之所以说这个方法重要,是因为我们可以把这个方法看成是PhoneGap的入口函
数。PhoneGap在loadUrl里做了一些初始化工作,会调用到init()函数。
/** * Create and initialize web container with default web view objects. */ public void init() { CordovaWebView webView = new CordovaWebView(DroidGap.this); this.init(webView, new CordovaWebViewClient(this, webView), new CordovaChromeClient(this, webView)); }
init()完成了WebView的设置等重要工作,这对理解PhoneGap底层原理有很重要的作用。从代码中可以看到,初始化时首先实例化了
CordovaWebView类型的webView对象,这里的CordovaWebView继承Android WebView类,后面会有讲到。然后传入不同参数重载了init()方
法。
传入参数包括webView、CordovaWebViewClient类型的webViewClient对象和CordovaChromeClient类型ChromeClient对
象。CordovaWebViewClient和CordovaChromeClient分别继承Android WebViewClient和ChromeClient类,这两个类在后面也会提到。
1 /** 2 * Initialize web container with web view objects. 3 * 4 * @param webView 5 * @param webViewClient 6 * @param webChromeClient 7 */ 8 public void init(CordovaWebView webView, CordovaWebViewClient webViewClient, CordovaChromeClient webChromeClient) { 9 LOG.d(TAG, "DroidGap.init()"); 10 11 // Set up web container 12 this.appView = webView; 13 this.appView.setId(100); 14 15 this.appView.setWebViewClient(webViewClient); 16 this.appView.setWebChromeClient(webChromeClient); 17 webViewClient.setWebView(this.appView); 18 webChromeClient.setWebView(this.appView); 19 20 this.appView.setLayoutParams(new LinearLayout.LayoutParams( 21 ViewGroup.LayoutParams.MATCH_PARENT, 22 ViewGroup.LayoutParams.MATCH_PARENT, 23 1.0F)); 24 25 // Add web view but make it invisible while loading URL 26 this.appView.setVisibility(View.INVISIBLE); 27 this.root.addView(this.appView); 28 setContentView(this.root); 29 30 // Clear cancel flag 31 this.cancelLoadUrl = false; 32 33 }
这里的appView也是CordovaWebView类型,是DroidGap类的一个属性。对appView进行了初始化设置,appView实际就是刚才实例化的
webView,然后设置它的webViewClient和ChromeClient分别为刚才的传入参数webViewClient和ChromeClient。
可能会有人不理解为什么要设置这两个Client呢?这里需要先从Android原生角度介绍一下WebView组件以及WebViewClient和ChromeClient这两个类的
区别:
WebView组件
WebView组件实质是移动设备的内置浏览器。WebView这个内置浏览器特性是Web能被打包成本地客户端的基础,可方便的用HTML5、CSS3页面布局,这是
移动Web技术的优势相对于原生开发。
PhoneGap针对不同平台的WebView做了扩展和封装,使WebView这个组件变成可访问设备本地API的强大浏览器,所以开发人员在PhoneGap框架下可通过
JavaScript访问设备本地API。
WebViewClient
WebViewClient帮助WebView处理各种通知、请求事件的,具体来说包括:
onLoadResource()
onPageStarted()
onPageFinished()
onReceiveError()
onReceivedHttpAuthRequest()
WebChromeClient
WebChromeClient是辅助WebView处理Javascript的对话框,网站图标,网站title,加载进度等
onCloseWindow(关闭WebView)
onCreateWindow()
onJsAlert (WebView上alert是弹不出来东西的,需要定制你的WebChromeClient处理弹出)
onJsPrompt()
onJsConfirm()
onProgressChanged()
onReceivedIcon()
onReceivedTitle()