Theme類、程序的分類、SimpleAdapter類、ANR和FC
Android中Theme類可以繼承?
不可以
解析:我們先看一下AndroidManifest.xml檔案,裡面有這麼一行程式碼
android:theme="@style/AppTheme"
即對主題樣式的指定、設定,接下來進入styles.xml檔案
<style name="AppTheme1" parent="Theme.AppCompat.Light"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <style name="Animation" /> <style name="Animation.Dialog"> <item name="windowEnterAnimation">@anim/dialog_enter</item> <item name="windowExitAnimation">@anim/dialog_exit</item> </style>
這裡的樣式程式碼,可以分為兩種,一種是使用parent,代表該樣式來自哪裡?一般在java裡,我們都說繼承,parent即對應父類,另一種是使用已有的style名字後直接加.來表示(這種是自定義的style),這麼看來,似乎Theme類是可以繼承的,我就是這樣認識錯的。下面我們再從用程式碼設定主題的方面來看一下,
直接在activity裡就可以設定setTheme(); 我們點進去
@Override public void setTheme(@StyleRes final int resid) { super.setTheme(resid); // Keep hold of the theme id so that we can re-set it later if needed mThemeId = resid; }
我們來看一下這個mThemeId是如何使用的(只看重點,感興趣自己看原始碼)
if (Build.VERSION.SDK_INT >= 23) {
onApplyThemeResource(getTheme(), mThemeId, false);
} else {
setTheme(mThemeId);
}
這裡就對6.0上下進行了不同的方法設定,我們先看6.0以上的系統
@Override protected void onApplyThemeResource(Resources.Theme theme, @StyleRes int resid, boolean first) { if (mParent == null) { super.onApplyThemeResource(theme, resid, first); } else { try { theme.setTo(mParent.getTheme()); } catch (Exception e) { // Empty } theme.applyStyle(resid, false); } // Get the primary color and update the TaskDescription for this activity TypedArray a = theme.obtainStyledAttributes( com.android.internal.R.styleable.ActivityTaskDescription); if (mTaskDescription.getPrimaryColor() == 0) { int colorPrimary = a.getColor( com.android.internal.R.styleable.ActivityTaskDescription_colorPrimary, 0); if (colorPrimary != 0 && Color.alpha(colorPrimary) == 0xFF) { mTaskDescription.setPrimaryColor(colorPrimary); } } int colorBackground = a.getColor( com.android.internal.R.styleable.ActivityTaskDescription_colorBackground, 0); if (colorBackground != 0 && Color.alpha(colorBackground) == 0xFF) { mTaskDescription.setBackgroundColor(colorBackground); } final int statusBarColor = a.getColor( com.android.internal.R.styleable.ActivityTaskDescription_statusBarColor, 0); if (statusBarColor != 0) { mTaskDescription.setStatusBarColor(statusBarColor); } final int navigationBarColor = a.getColor( com.android.internal.R.styleable.ActivityTaskDescription_navigationBarColor, 0); if (navigationBarColor != 0) { mTaskDescription.setNavigationBarColor(navigationBarColor); } a.recycle(); setTaskDescription(mTaskDescription); }
這裡面看著是否和自定義view有點相似,大概就是一層層摳出來,像我們前面寫的style有parent,點到為止,這裡不是研究這個問題。6.0以下的,就直接看他的父類方法
@Override
public void setTheme(int resid) {
if (mThemeResource != resid) {
mThemeResource = resid;
initializeTheme();
}
}
發現,mThemeResource的使用和6.0以上類似(不做重點),繼續initializeTheme(初始化主題)
private void initializeTheme() {
final boolean first = mTheme == null;
if (first) {
mTheme = getResources().newTheme();
final Resources.Theme theme = getBaseContext().getTheme();
if (theme != null) {
mTheme.setTo(theme);
}
}
onApplyThemeResource(mTheme, mThemeResource, first);
}
重點出現了,Theme是用final修飾的,很明顯不能被繼承。
程序的分類
前臺程序
使用者當前操作所必需的程序。如果一個程序滿足以下任一條件,即視為前臺程序:
託管使用者正在互動的 Activity(已呼叫 Activity 的 onResume() 方法)
託管某個 Service,後者繫結到使用者正在互動的 Activity
託管正在“前臺”執行的 Service(服務已呼叫 startForeground())
託管正執行一個生命週期回撥的 Service(onCreate()、onStart() 或 onDestroy())
託管正執行其 onReceive() 方法的 BroadcastReceiver
通常,在任意給定時間前臺程序都為數不多。只有在記憶體不足以支援它們同時繼續執行這一萬不得已的情況下,系統才會終止它們。 此時,裝置往往已達到記憶體分頁狀態,因此需要終止一些前臺程序來確保使用者介面正常響應。
可見程序
沒有任何前臺元件、但仍會影響使用者在螢幕上所見內容的程序。 如果一個程序滿足以下任一條件,即視為可見程序:
託管不在前臺、但仍對使用者可見的 Activity(已呼叫其 onPause() 方法)。例如,如果前臺 Activity 啟動了一個對話方塊,允許在其後顯示上一 Activity,則有可能會發生這種情況。
託管繫結到可見(或前臺)Activity 的 Service。
可見程序被視為是極其重要的程序,除非為了維持所有前臺程序同時執行而必須終止,否則系統不會終止這些程序。
服務程序
正在執行已使用 startService() 方法啟動的服務且不屬於上述兩個更高類別程序的程序。儘管服務程序與使用者所見內容沒有直接關聯,但是它們通常在執行一些使用者關心的操作(例如,在後臺播放音樂或從網路下載資料)。因此,除非記憶體不足以維持所有前臺程序和可見程序同時執行,否則系統會讓服務程序保持執行狀態。
後臺程序
包含目前對使用者不可見的 Activity 的程序(已呼叫 Activity 的 onStop() 方法)。這些程序對使用者體驗沒有直接影響,系統可能隨時終止它們,以回收記憶體供前臺程序、可見程序或服務程序使用。 通常會有很多後臺程序在執行,因此它們會儲存在 LRU (最近最少使用)列表中,以確保包含使用者最近檢視的 Activity 的程序最後一個被終止。如果某個 Activity 正確實現了生命週期方法,並儲存了其當前狀態,則終止其程序不會對使用者體驗產生明顯影響,因為當用戶導航回該 Activity 時,Activity 會恢復其所有可見狀態。 有關儲存和恢復狀態的資訊,請參閱 Activity文件。
空程序
不含任何活動應用元件的程序。保留這種程序的的唯一目的是用作快取,以縮短下次在其中執行元件所需的啟動時間。 為使總體系統資源在程序快取和底層核心快取之間保持平衡,系統往往會終止這些程序。
SimpleAdapter類支援的繫結view型別
if (!bound) {
//該view是否實現checkable介面
if (v instanceof Checkable) {
if (data instanceof Boolean) {
((Checkable) v).setChecked((Boolean) data);
//該view是否是TextView
} else if (v instanceof TextView) {
// Note: keep the instanceof TextView check at the bottom of these
// ifs since a lot of views are TextViews (e.g. CheckBoxes).
setViewText((TextView) v, text);
} else {
throw new IllegalStateException(v.getClass().getName() +
" should be bound to a Boolean, not a " +
(data == null ? "<unknown type>" : data.getClass()));
}
} else if (v instanceof TextView) {
// Note: keep the instanceof TextView check at the bottom of these
// ifs since a lot of views are TextViews (e.g. CheckBoxes).
setViewText((TextView) v, text);
//該view是否是ImageView
} else if (v instanceof ImageView) {
if (data instanceof Integer) {
setViewImage((ImageView) v, (Integer) data);
} else {
setViewImage((ImageView) v, text);
}
} else {
throw new IllegalStateException(v.getClass().getName() + " is not a " +
" view that can be bounds by this SimpleAdapter");
}
}
以上原始碼很明顯能看出來使用SimpleAdapter作為介面卡時,支援三種類型的 View,而且是按照如下順序進行匹配: 實現Checkable介面 、TextView、 ImageView,但面試或筆試的時候,問你的不一定是這麼明顯,比如CompoundButton是否支援?它支援是因為它實現了checkable介面還是TextView的子類?因為這是按照順序判斷的,所以CompoundButton實現了Checkable介面,所以被SimpleAdapter支援,雖然它同樣可以在第二個判斷裡通過,但不考慮。
ANR和FC
ANR(Application Not Respone):程式無響應,有可能程式會再次響應
出現條件:1.當用戶輸入事件5s內沒有得到響應,將彈出ANR對話方塊 2.廣播接收者的onReceive()執行時間超過10s
FC(Force close):程式丟擲異常,會強制退出
出現條件:Error 、OOM,記憶體溢位 、StackOverFlowError 、Runtime,比如說空指標異常
關於這兩種情況如何避免,以後再說,這裡主要是要說下正確理解和區分這兩種情況。