StartUML簡易分析
代碼分析:
從Setting-AndroidManifest開始
<application android:label="@string/settings_label"
android:icon="@mipmap/ic_launcher_settings"
android:taskAffinity=""
android:theme="@style/Theme.Settings"
android:hardwareAccelerated="true"
android:requiredForAllUsers="true"
android:supportsRtl="true"
android:allowBackup="false"
android:usesCleartextTraffic="true">
<!-- Settings -->
<activity android:name="Settings"
android:taskAffinity="com.android.settings"
android:label="@string/settings_label_launcher"
android:launchMode="singleTask">
<intent-filter android:priority="1">
<action android:name="android.settings.SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>
可以看出是從Settings開始加載
Settings繼承自SettingsActivity
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 PrivateVolumeForgetActivity extends SettingsActivity { /* empty */ }
public static class PrivateVolumeSettingsActivity extends SettingsActivity { /* empty */ }
public static class PublicVolumeSettingsActivity 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 class SettingsActivity extends Activity
implements PreferenceManager.OnPreferenceTreeClickListener,
PreferenceFragment.OnPreferenceStartFragmentCallback,
ButtonBarHandler, FragmentManager.OnBackStackChangedListener,
SearchView.OnQueryTextListener, SearchView.OnCloseListener,
MenuItem.OnActionExpandListener {
...
@Override
protected void onCreate(Bundle savedState) {
super.onCreate(savedState);
// Should happen before any call to getIntent()
getMetaData();
......
}
//初始化第一步擷取資料
/**
* 如獲得資料成功,
* 則表示不是直接啟動設定的(比較啟動的是:BluetoothSettingsActivity),
* 則不會顯示所有的設定項,隻顯示具體的設定項(比較藍牙設定)。
*/
private void getMetaData() {
try {
ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
PackageManager.GET_META_DATA);
if (ai == null || ai.metaData == null) return;
mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
} catch (NameNotFoundException nnfe) {
// No recovery
Log.d(LOG_TAG, "Cannot get Metadata for: " + getComponentName().toString());
}
}
可以看出第一步先是進行了fragment的判斷--接着onCreate其他函數往下看
...
//判斷目前的類是哪個具體的類
mIsShowingDashboard = className.equals(Settings.class.getName());
// This is a "Sub Settings" when:
// - this is a real SubSettings
// - or :settings:show_fragment_as_subsetting is passed to the Intent
//如果是通過點選桌面的設定進入,那麼mIsShowingDashboard的值就為真。
final boolean isSubSettings = this instanceof SubSettings ||
intent.getBooleanExtra(EXTRA_SHOW_FRAGMENT_AS_SUBSETTING, false);
....
//設定進入的子產品
setContentView(mIsShowingDashboard ?
R.layout.settings_main_dashboard : R.layout.settings_main_prefs);
....
if (savedState != null) {
....
}
....
} else {
if ((initialFragmentName != null) && !mIsShowingDashboard) {
....
} 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這個片段。
* 接下來看一下DashboardSummary.java這個類了。
*/
switchToFragment(DashboardSummary.class.getName(), null, false, false,
mInitialTitleResId, mInitialTitle, false);
}
}
關鍵方法...進行了Fragment界面加載-->跳轉到DashboardSummary.class檢視
根據上訴代碼分析...大緻布局可以了解為如下
---實際調用了的布局自上而下依次是---
R.layout.settings_main_dashboard
R.layout.dashboard
R.layout.dashboard_category
DashboardTile--framelayout
根據如上分析--大緻如下
switchToFragment(DashboardSummary.class.getName(), null, false, false,
mInitialTitleResId, mInitialTitle, false);
public class DashboardSummary extends InstrumentedFragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mLayoutInflater = inflater;
//加載布局
final View rootView = inflater.inflate(R.layout.dashboard, container, false);
mDashboard = (ViewGroup) rootView.findViewById(R.id.dashboard_container);
return rootView;
}
緊接着檢視onResume方法
@Override
public void onResume() {
super.onResume();
//顯示各個設定的選項
sendRebuildUI();
final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
filter.addDataScheme("package");
getActivity().registerReceiver(mHomePackageReceiver, filter);
}
private void sendRebuildUI() {
if (!mHandler.hasMessages(MSG_REBUILD_UI)) {
mHandler.sendEmptyMessage(MSG_REBUILD_UI);
}
}
private static final int MSG_REBUILD_UI = 1;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REBUILD_UI: {
final Context context = getActivity();
rebuildUI(context);
} break;
}
}
};
下面是布局進行動态加在的方法
private void rebuildUI(Context context) {
if (!isAdded()) {
Log.w(LOG_TAG, "Cannot build the DashboardSummary UI yet as the Fragment is not added");
return;
}
long start = System.currentTimeMillis();
final Resources res = getResources();
mDashboard.removeAllViews();
//加在UI之前 先加在資料
List<DashboardCategory> 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);
}
long delta = System.currentTimeMillis() - start;
Log.d(LOG_TAG, "rebuildUI took: " + delta + " ms");
}
中間調用了一次SettingsActivity中解析XML資料的方法
public List<DashboardCategory> getDashboardCategories(boolean forceRefresh) {
if (forceRefresh || mCategories.size() == 0) {
//更新資料--xml解析
buildDashboardCategories(mCategories);
}
return mCategories;
}
對應ID看對應代碼,這樣才是最友善的