Android5.0 Lollipop Setting启动分析
2015-11-14 16:57
435 查看
1.Android5.0和前版本的Setting实现方式有区别,需要看较早版本的请戳http://blog.csdn.net/wangjinyu501/article/details/22077803
2.本文主要是对Setting的启动进行大致分析
可以看出Setting类主要是继承了SettingsActivity,然后创建了很多的内部类。直接转到SettingsActivity。既然是Activity直奔onCreate方法。
终于加载xml文件了,可知本次加载的是R.layout.settings_main_dashboard,该xml文件代码如下:
除了一个FrameLayout什么都没有,猜测setting的很多设置项就是放在了这个id为main_content的FrameLayout中显示的。继续onCreate方法
重点在switchToFragment这个函数,猜测是将一个Fragment放在前文提到的id为main_content的FrameLayout中。
上述过程较为简单,核心就一句代码 transaction.replace(R.id.main_content, f),这句就是将f这个fragment放入id为main_content的FrameLayout中。那现在问题又来了,放入的这个名为DashboardSummary的fragment又是什么呢?下面进入DashboardSummary的分析。既然是fragment,抓住主要的几个方法就好了。
先看onCreateView:
就是加载一个R.layout.dashboard然后找出其中的dashboard_container。那看看这个dashboard是什么
进入sendRebuildUI
但是到底加进去的是什么呢?
秘密在getDashboardCategories()这里,经过一系列调用后,会调用 loadCategoriesFromResource(R.xml.dashboard_categories, categories);
而dashboard_categories:
总结就是:activity先加载一个空的layout,其中有FrameLayout,然后将一个fragment放进去,在fragment中也是先加载了一个仅有一个LinearLayout的layout,接着在这个LinearLayout中加载转化的对象,形成设置的初始界面,如下图:
2.本文主要是对Setting的启动进行大致分析
1.总概况
本文只分析启动过程2.Settings初始化流程
首先根据manifest文件找出最先启动的activity:Settings。该类具体代码如下: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 AppOpsSummaryActivity extends SettingsActivity { @Override public boolean isValidFragment(String className) { if (AppOpsSummary.class.getName().equals(className)) { return true; } return super.isValidFragment(className); } } public static class StorageUseActivity extends SettingsActivity { /* empty */ } public static class OtherSoundSettingsActivity extends SettingsActivity { /* empty */ } public static class QuickLaunchSettingsActivity extends SettingsActivity { /* empty */ } public static class TopLevelSettings extends SettingsActivity { /* empty */ } public static class ApnSettingsActivity extends SettingsActivity { /* empty */ } }
可以看出Setting类主要是继承了SettingsActivity,然后创建了很多的内部类。直接转到SettingsActivity。既然是Activity直奔onCreate方法。
getMetaData();//此函数在初始化时会直接返回 mIsShowingDashboard = className.equals(Settings.class.getName());//此时className和Settings.class一致,为true; setContentView(mIsShowingDashboard ? R.layout.settings_main_dashboard : R.layout.settings_main_prefs);
终于加载xml文件了,可知本次加载的是R.layout.settings_main_dashboard,该xml文件代码如下:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main_content" android:layout_height="match_parent" android:layout_width="match_parent" android:background="@color/dashboard_background_color" />
除了一个FrameLayout什么都没有,猜测setting的很多设置项就是放在了这个id为main_content的FrameLayout中显示的。继续onCreate方法
<span style="white-space:pre"> </span>mDisplayHomeAsUpEnabled = false; mDisplaySearch = true; mInitialTitleResId = R.string.dashboard_title;// <string name="dashboard_title">Settings</string> switchToFragment(DashboardSummary.class.getName(), null, false, false,mInitialTitleResId, mInitialTitle, false);
重点在switchToFragment这个函数,猜测是将一个Fragment放在前文提到的id为main_content的FrameLayout中。
private Fragment switchToFragment(String fragmentName, Bundle args, boolean validate, boolean addToBackStack, int titleResId, CharSequence title, boolean withTransition) { if (validate && !isValidFragment(fragmentName)) { throw new IllegalArgumentException("Invalid fragment for this activity: " + fragmentName); } Fragment f = Fragment.instantiate(this, fragmentName, args);//通过静态方法实例化一个fragment FragmentTransaction transaction = getFragmentManager().beginTransaction();//获取fragment操作集合 transaction.replace(R.id.main_content, f);//将原容器中的内容替换为f if (withTransition) { TransitionManager.beginDelayedTransition(mContent); } if (addToBackStack) { //在commit()方法之前,你可以调用addToBackStack(),把这个transaction加入back stack中去,这样按返回键时会出现被替换的fragment transaction.addToBackStack(SettingsActivity.BACK_STACK_PREFS); } if (titleResId > 0) { transaction.setBreadCrumbTitle(titleResId); } else if (title != null) { transaction.setBreadCrumbTitle(title); } transaction.commitAllowingStateLoss(); getFragmentManager().executePendingTransactions();//调用commit()方法并不能立即执行transaction中包含的改变动作,commit()方法把transaction加入activity的UI线程队列中。 // 但是,如果觉得有必要的话,可以调用executePendingTransactions()方法来立即执行commit()提供的transaction。 return f; }
上述过程较为简单,核心就一句代码 transaction.replace(R.id.main_content, f),这句就是将f这个fragment放入id为main_content的FrameLayout中。那现在问题又来了,放入的这个名为DashboardSummary的fragment又是什么呢?下面进入DashboardSummary的分析。既然是fragment,抓住主要的几个方法就好了。
先看onCreateView:
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; }
就是加载一个R.layout.dashboard然后找出其中的dashboard_container。那看看这个dashboard是什么
<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" /> </ScrollView>也很简单,就是一个id为dashboard_container的LinearLayout,猜测这个dashboard_container为真正放置设置项的地方。既然onCreateView中没有,就到onResume中去找。
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); }
进入sendRebuildUI
private void sendRebuildUI() { if (!mHandler.hasMessages(MSG_REBUILD_UI)) { mHandler.sendEmptyMessage(MSG_REBUILD_UI); } }发送一个MSG_REBUILD_UI的消息;如何处理呢?
switch (msg.what) { case MSG_REBUILD_UI: { final Context context = getActivity(); rebuildUI(context); } break;调用rebuildUI方法:
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(); List<DashboardCategory> categories = ((SettingsActivity) context).getDashboardCategories(true);//非常重要的一句,获取DashboardCategory 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"); }这段代码就是加载设置界面的:将每一个DashboardCategory取出,并且找出其中包含的DashboardTile形成DashboardTileView,最后显示在界面。
但是到底加进去的是什么呢?
秘密在getDashboardCategories()这里,经过一系列调用后,会调用 loadCategoriesFromResource(R.xml.dashboard_categories, categories);
而dashboard_categories:
<dashboard-categories xmlns:android="http://schemas.android.com/apk/res/android"> <!-- WIRELESS and NETWORKS --> <dashboard-category android:id="@+id/wireless_section" android:title="@string/header_category_wireless_networks" > <!-- Wifi --> <dashboard-tile android:id="@+id/wifi_settings" android:title="@string/wifi_settings_title" android:fragment="com.android.settings.wifi.WifiSettings" android:icon="@drawable/ic_settings_wireless" /> <!-- Bluetooth --> <dashboard-tile android:id="@+id/bluetooth_settings" android:title="@string/bluetooth_settings_title" android:fragment="com.android.settings.bluetooth.BluetoothSettings" android:icon="@drawable/ic_settings_bluetooth2" /> <!-- SIM Cards --> <dashboard-tile android:id="@+id/sim_settings" android:title="@string/sim_settings_title" android:fragment="com.android.settings.sim.SimSettings" android:icon="@drawable/ic_sim_sd" /> <!-- Data Usage --> <dashboard-tile android:id="@+id/data_usage_settings" android:title="@string/data_usage_summary_title" android:fragment="com.android.settings.DataUsageSummary" android:icon="@drawable/ic_settings_data_usage" /> <!-- Operator hook --> <dashboard-tile android:id="@+id/operator_settings" android:fragment="com.android.settings.WirelessSettings" > <intent android:action="com.android.settings.OPERATOR_APPLICATION_SETTING" /> </dashboard-tile> <!-- Other wireless and network controls --> <dashboard-tile android:id="@+id/wireless_settings" android:title="@string/radio_controls_title" android:fragment="com.android.settings.WirelessSettings" android:icon="@drawable/ic_settings_more" /> </dashboard-category> <!-- DEVICE --> <dashboard-category android:id="@+id/device_section" android:title="@string/header_category_device" > <!-- Home --> <dashboard-tile android:id="@+id/home_settings" android:title="@string/home_settings" android:fragment="com.android.settings.HomeSettings" android:icon="@drawable/ic_settings_home" /> <!-- Display --> <dashboard-tile android:id="@+id/display_settings" android:title="@string/display_settings" android:fragment="com.android.settings.DisplaySettings" android:icon="@drawable/ic_settings_display" /> <!-- Notifications --> <dashboard-tile android:id="@+id/notification_settings" android:title="@string/notification_settings" android:fragment="com.android.settings.notification.NotificationSettings" android:icon="@drawable/ic_settings_notifications" /> <!-- Storage --> <dashboard-tile android:id="@+id/storage_settings" android:title="@string/storage_settings" android:fragment="com.android.settings.deviceinfo.Memory" android:icon="@drawable/ic_settings_storage" /> <!-- Battery --> <dashboard-tile android:id="@+id/battery_settings" android:title="@string/power_usage_summary_title" android:fragment="com.android.settings.fuelgauge.PowerUsageSummary" android:icon="@drawable/ic_settings_battery" /> <!-- Application Settings --> <dashboard-tile android:id="@+id/application_settings" android:title="@string/applications_settings" android:fragment="com.android.settings.applications.ManageApplications" android:icon="@drawable/ic_settings_applications" /> <!-- Manage users --> <dashboard-tile android:id="@+id/user_settings" android:title="@string/user_settings_title" android:fragment="com.android.settings.users.UserSettings" android:icon="@drawable/ic_settings_multiuser" /> <!-- Manage NFC payment apps --> <dashboard-tile android:id="@+id/nfc_payment_settings" android:title="@string/nfc_payment_settings_title" android:fragment="com.android.settings.nfc.PaymentSettings" android:icon="@drawable/ic_settings_nfc_payment" /> <!-- Manufacturer hook --> <dashboard-tile android:id="@+id/manufacturer_settings" android:fragment="com.android.settings.WirelessSettings"> <intent android:action="com.android.settings.MANUFACTURER_APPLICATION_SETTING" /> </dashboard-tile> </dashboard-category>每个dashboard-tile就是一个preference,点击后就会转到对应的fragment。
总结就是:activity先加载一个空的layout,其中有FrameLayout,然后将一个fragment放进去,在fragment中也是先加载了一个仅有一个LinearLayout的layout,接着在这个LinearLayout中加载转化的对象,形成设置的初始界面,如下图:
相关文章推荐
- Android Cursor(游标)
- Android Studio 编译错误:找不到符号
- android 语音识别 语音手电(一)
- Android基础入门教程——10.11 传感器专题(2)——方向传感器
- Android UsageStatsService源码
- IDEA引入第三方开源库的几点注意事项
- Android代码强制区分规范
- Android view的工作原理(Android开发艺术探索随笔)
- Android Studio 导入jar ,so 及 开源库
- 关于Android中ImageView中tint属性的一点点整理
- android:descendantFocusability用法简析
- Android-自定义多TAB悬浮控件实现蘑菇街首页效果
- Android性能分析工具-TraceView
- 推荐大家一个不错android模拟器工具Genymotion
- android studio 添加快捷按钮.
- Android学习:TextUtils类介绍
- 关于android中数据持久化存储的方法的知识整理
- 一个android的各种控件库
- Android实现TextView字符串波浪式跳动
- 安卓学习笔记一 —— Activity的一些使用技巧