Android M Settings界面加载流程分析
程序员文章站
2022-05-23 19:57:17
...
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看对应代码,这样才是最方便的
上一篇: 机器人开始参与养老
推荐阅读
-
Android6.0 keyguard锁屏加载流程分析
-
分析Android 11.0Settings源码之主界面加载
-
Android 10.0 Settings源码分析之主界面加载(二)
-
Android5.1的系统Settings主界面UI显示流程源码分析
-
Android M Settings界面加载流程分析
-
Android 8.0 Settings流程分析与变动
-
Android 图片加载框架Glide主流程源码分析
-
Android6.0 keyguard锁屏加载流程分析
-
分析Android 11.0Settings源码之主界面加载
-
Android 10.0 Settings源码分析之主界面加载(二)