編輯:關於Android編程
先聲明:本人工作快兩年了,仍是菜鳥級別的,慚愧啊!以前遇到好多知識點都沒有記錄下來,感覺挺可惜的,現在有機會接觸Android 源碼。我們一個Android組的搞Setting,我覺得是得寫得東西,畢竟才接觸,現在只能看一段時間代碼,就先記錄下一些收獲吧,說多了就是淚~本文主要針對L平台上Settings模塊正常啟動流程做一個簡要分析,並試著分析一下Settings下面某選項的實現。
在之前的KK平台上Settings模塊的第一個Activity名字為Settings,其繼承的是PreferenceActivity,設置的每一個選項都是對應的一個Header對象,並且Header對象允許顯示switch控件,button控件,checkbox控件等。如下圖1.1,WLAN和藍牙上使用到了switch開關。但在L上面,WLAN和藍牙的這兩個開關已經去掉了,如圖1.2,在Settings模塊的首個頁面似乎就只是一個普通的Listview,那它用的還是不是Header呢?或者說取而代之的是什麼呢?繼續往下看吧~
圖片-1.1
圖片-1.2
L Settings模塊首界面為Settings,繼承自SettingsActivity,SettingsActivity繼承自Activity。
首先看一下Settings.java代碼可以發現它沒有重寫任何SettingsActiviy的方法,也沒有增加任何自己的方法,唯獨增加了許多靜態內部類,如:
/**
* Top-level Settings activity
*/
public class Settings extends SettingsActivity {
/*
* Settings subclasses for launching independently.
*/
public static class BluetoothSettingsActivity extends SettingsActivity { /* empty */ }
public static class WirelessSettingsActivity extends SettingsActivity { /* empty */ }
public static class SimSettingsActivity extends SettingsActivity { /* empty */ }
public static class TetherSettingsActivity extends SettingsActivity { /* empty */ }
public static class VpnSettingsActivity extends SettingsActivity { /* empty */ }
public static class DateTimeSettingsActivity extends SettingsActivity { /* empty */ }
public static class StorageSettingsActivity extends SettingsActivity { /* empty */ }
public static class WifiSettingsActivity extends SettingsActivity { /* empty */ }
public static class WifiP2pSettingsActivity extends SettingsActivity { /* empty */ }
public static class InputMethodAndLanguageSettingsActivity extends SettingsActivity { /* empty */ }
public static class KeyboardLayoutPickerActivity extends SettingsActivity { /* empty */ }
public static class InputMethodAndSubtypeEnablerActivity extends SettingsActivity { /* empty */ }
public static class VoiceInputSettingsActivity extends SettingsActivity { /* empty */ }
public static class SpellCheckersSettingsActivity extends SettingsActivity { /* empty */ }
public static class LocalePickerActivity extends SettingsActivity { /* empty */ }
public static class UserDictionarySettingsActivity extends SettingsActivity { /* empty */ }
public static class HomeSettingsActivity extends SettingsActivity { /* empty */ }
...
}
看注釋可以知道,這些子類是為了啟動特定獨立的Settings選項而創建的,例如在某個應用裡需要設置無線那麼只需要啟動 WirelessSettingsActivity 就可以了。
所以Settings模塊的啟動流程直接看SettingsActiviy就行了。
1. SettingsActivity.onCreate方法
onCreate方法是Activity的生命周期第一步,看看 SettingsActivity在這裡都做了些什麼?
// Should happen before any call to getIntent()
getMetaData();
這個方法用來獲得Activity的額外數據mFragmentClass,如果可以獲得這個數據,那麼下面會去顯示mFragmentClass對應的Activity。直接啟動Settings模塊不會獲得這個數據。
mIsShowingDashboard = className.equals(Settings.class.getName());
這一步很重要,因為我們是從Settings這個Activity過來的,所以這裡的 mIsShowingDashboard 為 true 。
// This is a "Sub Settings" when:
// - this is a real SubSettings
// - or :settings:show_fragment_as_subsetting is passed to the Intent
final boolean isSubSettings = className.equals(SubSettings.class.getName()) ||
intent.getBooleanExtra(EXTRA_SHOW_FRAGMENT_AS_SUBSETTING, false);
這個判斷很重要但很明顯這時isSubSettings的值是fasle,暫時忽略。
setContentView(mIsShowingDashboard ?
R.layout.settings_main_dashboard : R.layout.settings_main_prefs);
前面知道這裡的 mIsShowingDashboard為true,所以這裡使用的布局文件為R.layout.settings_main_dashboard。settings_main_dashboard.xml文件如下:
<framelayout android:background="@color/dashboard_background_color" android:id="@+id/main_content" android:layout_height="match_parent" android:layout_width="match_parent" xmlns:android="http://schemas.android.com/apk/res/android"></framelayout>
由於mIsShowingDashboard為true,直接走到下面這段
else {
// No UP affordance if we are displaying the main Dashboard
mDisplayHomeAsUpEnabled = false;
// Show Search affordance
mDisplaySearch = true;
mInitialTitleResId = R.string.dashboard_title;
switchToFragment(DashboardSummary.class.getName(), null, false, false,
mInitialTitleResId, mInitialTitle, false);
}
這裡看到switchToFragment這個方法,可以知道這裡是要切換DashboardSummary這個Fragment.
接下來就看看DashboardSummary是個什麼玩意?
dashboard中文意思是儀表盤,這裡是指DashboardSummary就是用來顯示Settings所有選項的。
在DashboardSummary的onCreateView裡加載了這個布局文件R.layout.dashboard
<code class=" hljs perl"><scrollview xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/dashboard" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbarstyle="outsideOverlay" android:cliptopadding="false"> <linearlayout android:id="@+id/dashboard_container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center_horizontal" android:paddingstart="@dimen/dashboard_padding_start" android:paddingend="@dimen/dashboard_padding_end" android:paddingtop="@dimen/dashboard_padding_top" android:paddingbottom="@dimen/dashboard_padding_bottom" android:orientation="vertical"> </linearlayout></scrollview></code>
看了上面的布局文件可以知道Settings的選項視圖應該就是顯示在dashboard_container中了。
DashboardSummary走完onCreateView方法後會走onResume,然後一路下來又會調到SettingsActivity的
loadCategoriesFromResource(R.xml.dashboard_categories, categories);
這一步是通過 R.xml.dashboard_categories來加載categories,這裡的categorys為ArrayList mCategories。接著來看看dashboard_categories.xml這個文件吧
vcnlfd2lyZWxlc3NfbmV0d29ya3M=">
根據這個文件我們可以知道了,所謂的dashboard就是Settings模塊首界面的一個抽象。而dashboard-categorys則是設置分類集合的抽象,而dashboard-category是分類的抽象,dashboard-tile就是分類下每個選項的抽象了。代碼中的List對應dashboard-categorys, DashboardCategory對應dashboard-category,而dashboard-tile則對因代碼中的DashboardTile。
當加載完這些對象後SettingsActivity會將得到的 mCategories 返回給DashboardSummary來初始化Settings的設置選項。
下面這段代碼就是DashboardSummary.rebuildUI()中完成界面的初始化
long start = System.currentTimeMillis();
final Resources res = getResources();
mDashboard.removeAllViews();
List categories =
((SettingsActivity) context).getDashboardCategories(true);
final int count = categories.size();
for (int n = 0; n < count; n++) {
DashboardCategory category = categories.get(n);
View categoryView = mLayoutInflater.inflate(R.layout.dashboard_category, mDashboard,
false);
TextView categoryLabel = (TextView) categoryView.findViewById(R.id.category_title);
categoryLabel.setText(category.getTitle(res));
ViewGroup categoryContent =
(ViewGroup) categoryView.findViewById(R.id.category_content);
final int tilesCount = category.getTilesCount();
for (int i = 0; i < tilesCount; i++) {
DashboardTile tile = category.getTile(i);
DashboardTileView tileView = new DashboardTileView(context);
updateTileView(context, res, tile, tileView.getImageView(),
tileView.getTitleTextView(), tileView.getStatusTextView());
tileView.setTile(tile);
categoryContent.addView(tileView);
}
// Add the category
mDashboard.addView(categoryView);
}
這段代碼我就不具體分析了,邏輯很簡單,遍歷categories這個列表來獲取DashboardCategory對象,將所有DashboardCategory對象和DashboardCategory對象中的DashboardTile對象轉化為視圖對象並添加到主視圖對象mDashboard中。
到這裡SettingsActivity的onCreate方法就算結束了。總結一下,
1.onCreate完成的任務是切換DashboardSmmary這個Fragment,然後從dashboard_categories.xml中讀取預先配置好的文件來初始化Settings的首界面視圖。
2.L中捨棄了Header類,取而代之的是DashboardCategory和DashboardTile類。
當你提交代碼的時候,如果出現各種你不想提交的文件的時候,你也許會選擇在項目左邊欄選中java–>src來進行提交,這樣操作是沒有問題,但是如果你想使用
每次應用程序運行時,應用程序的application類保持實例化的狀態。通過擴展applicaiton類,可以完成以下3項工作: 1.對android運行時廣播的應用程序
Android M指紋的資料太少,經過一段時間閱讀原生Android代碼,寫了以下例子,貢獻出來給需要幫助的人。 以下內容基於64位的高通CPU,搭載fpc1020芯片
前言SQLite是一款輕型的數據庫,是遵守ACID的關系型數據庫管理系統,它包含在一個相對小的C庫中。它是D.RichardHipp建立的公有領域項目,設計目標是嵌入式的