接着分析browser中的首启动activity,通过AndroidManifest可以看出Browser初始化启动的Activity为BrowserActivity
<activity android:name="BrowserActivity" android:label="@string/application_name" android:launchMode="singleTask" android:alwaysRetainTaskState="true" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:theme="@style/BrowserTheme" android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="android.speech.action.VOICE_SEARCH_RESULTS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<!-- For these schemes were not particular MIME type has been supplied, we are a good candidate. -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:scheme="about" />
</intent-filter>
<!-- For these schemes where any of these particular MIME types have been supplied, we are a good candidate. -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:mimeType="text/html"/>
<data android:mimeType="text/plain"/>
<data android:mimeType="application/xhtml+xml"/>
<data android:mimeType="application/vnd.wap.xhtml+xml"/>
</intent-filter>
<!-- Accept inbound NFC URLs at a low priority -->
<intent-filter android:priority="-101">
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
<data android:scheme="https" />
</intent-filter>
<!-- We are also the main entry point of the browser. -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.APP_BROWSER" />
</intent-filter>
<!-- The maps app is a much better experience, so it's not worth having this at all... especially for a demo! <intent-filter android:label="Map In Browser"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="vnd.android.cursor.item/postal-address" /> </intent-filter> -->
<intent-filter>
<action android:name="android.intent.action.WEB_SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="" />
<data android:scheme="http" />
<data android:scheme="https" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MEDIA_SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="android.app.searchable" android:resource="@xml/searchable" />
</activity>
1、BrowserActivity定义的launchMode为singleTask。
singleTask的作用是:任务栈中保持只有一个自己的实例。如果任务栈存在这个实例,且在栈顶,则直接启动这个实例,无需创建新的activity实例
如果存在这个实例,但是不在栈顶的位置上,则销毁此activity实例以上的所有activity实例
详细介绍可参考,转载请注明:
http://www.cnblogs.com/xiaoQLu/archive/2011/09/29/2195742.html
http://blog.csdn.net/wdaming1986/article/details/7304191
2.BrowserActivity定义了许多intent-filter来过滤intent,例如通过intent-filter来拦截http/https 协议的请求,以及内容类型为text/html、text/plain、application/xhtml+xml、application/vnd.wap.xhtml+xml的请求。
接下来分析BrowserActivity.java,Activity启动之后,首先会执行onCreate 方法
public void onCreate(Bundle icicle) {
if (LOGV_ENABLED) {
Log.v(LOGTAG, this + " onStart, has state: "
+ (icicle == null ? "false" : "true"));
}
super.onCreate(icicle);
if (shouldIgnoreIntents()) {
finish();
return;
}
// If this was a web search request, pass it on to the default web
// search provider and finish this activity.
if (IntentHandler.handleWebSearchIntent(this, null, getIntent())) {
finish();
return;
}
mController = createController();
Intent intent = (icicle == null) ? getIntent() : null;
mController.start(intent);
}
首先看shouldIgnoreIntents() 方法:
private boolean shouldIgnoreIntents() {
// Only process intents if the screen is on and the device is unlocked
// aka, if we will be user-visible
if (mKeyguardManager == null) {
mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
}
if (mPowerManager == null) {
mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
}
boolean ignore = !mPowerManager.isScreenOn();
ignore |= mKeyguardManager.inKeyguardRestrictedInputMode();
if (LOGV_ENABLED) {
Log.v(LOGTAG, "ignore intents: " + ignore);
}
return ignore;
}
如果当前屏幕变暗,或者处于锁屏状态,则忽略这次请求。
createController方法用来创建Controller核心控制器,Controller实现UiController接口
private Controller createController() {
Controller controller = new Controller(this);
boolean xlarge = isTablet(this);
UI ui = null;
if (xlarge) {
ui = new XLargeUi(this, controller);
} else {
ui = new PhoneUi(this, controller);
}
controller.setUi(ui);
return controller;
}
如果是平板,创建的UI实例为XLargeUi,如果不是平板,则创建的UI实例为PhoneUi,之后将创建的UI传递到Controller中,这块使用的设计模块是策略模式,在屏幕不同的版本时选用不同的策略,也就是不同的UI实例,就像volley初始化HttpStack那样
if (Build.VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
整个BrowserActivity中所有的事件回调,都会委托Controller去执行,这样整个Activity的代码体积将会变得很小。开发模式很像大名鼎鼎的MVP模式,UI(V)保留着Controller(P)的引用,Controller(P)保留着UI(V)的引用,并且两者都是通过定义好的接口进行交互。