Settings的界面如下:
你知道这些条目是怎么显示出来的, 点击某个条目又是进入到哪里了呢? 下面我们来分析分析。
从AndroidManifest里可以看出,上面的页面对应的是Settings.java,我把它定义为主界面吧,我们来看看它的代码:
就是定义里了很多Activity,实现部分都是空的,父类帮它们实现了所有的功能。他们的父类都是SettingsActivity,Settings自己的父类也是SettingsActivity,
而SettingsActivity是继承SettingsDrawerActivity的。
启动主界面自然会调用它的onCreate,没有!那自然就会调用它父类SettingsActivity的onCreate。上关键代码:
getMetaData代码:
注:public static final String META_DATA_KEY_FRAGMENT_CLASS = "com.android.settings.FRAGMENT_CLASS";
getMetaData就是从AndroidManifest里得到Activity定义的<meta-data 打头的信息,然后获得"com.android.settings.FRAGMENT_CLASS"的值。
对于主界面来说它没有定义"com.android.settings.FRAGMENT_CLASS"的值,那么mFragmentClass就是空的。继续上onCreate的代码:
第一次进入到主界面时mIsShowingDashboard是等于true的,那么就会swtich到DashboardContainerFragment。上DashboardContainerFragment关键代码:
这里返回的是DashboardSummary。DashboardSummary里有一个FocusRecyclerView对象mDashboard,
Settings里的每个item就是显示在这个RecyclerView里的,我们稍后在研究这个RecyclerView。
DashboardSummary的onCrreate代码:
SettingsDrawerActivity的getDashboardCategories:
TileUtils的getCategories:
getTilesForAction里会调用getTilesForIntent,getTilesForIntent里会调用queryIntentActivitiesAsUser来查找符合条件的activity的<meta-data 信息。
这里的条件指的是:
1)特定的包名。
2)Activity的定义中,<intent-filter 有指定的<action参数。
看看getTilesForIntent部分代码:
在这个函数里,我加了打印,部分结果如下:
那我来看看它对应activity的定义部分:
这里title的值还要说下,如果在<meta-data 里定义了“com.android.settings.title”,那title的值就是它对应的值。
如果没定义“com.android.settings.title”,title的值就是android:lable的值。
我们再回到TileUtils的getCategories里面,执行完getTilesForAction后的部分。createCategory就是创建一个大项,
这里就是创建了4个大项,分别是:Wireless & networks、Device、Personal和System。createCategory里有个List<Tile>链表,
存放的是它下面挂的Tile。比如Wireless&networks下挂的就是Wi-Fi、Bluetooth、Data usage和More。
TileUtils的getCategories的最后两次调用了Collections.sort,就是根据权重对大项和大项里的Tile进行排序,权重大的显示在前面。
到这里Setting里要显示的内容算是得到了,那是怎么显示在UI上的呢?我们继续研究。
来看ashboardSummary来的onViewCreated函数:
得到recycleView,设置它的Adapter,然后调用rebuildUI,接着都会调用mAdapter.setCategoriesAndSuggestions(categories, tiles),
setCategoriesAndSuggestions里会调用recountItems,recountItems的部分代码如下:
countItem表示的就是要显示前面解析出来的大项和大项里的tile,然后调用notifyDataSetChanged,那settints所有的内容就是显示出来了。
来看看DashboardAdapter的onBindViewHolder。
onBindCategory就是在相应的位置显示"Wireless&networks"、"Device"、"Personal"、“System“ 这几个字符串。
onBindTile就是显示如”Wireless&networks“下面的子项的:Wi-Fi、Bluetooth、Date usage、More。这里调用了setOnClickListerner,
那肯定就是我们按Enter键对应的代码了,后面再研究。
SettingsActivity的onCreate函数执行完后,会执行onStart函数,onStart里会执行updateTilesList,然后执行doUpdateTilesList。
doUpdateTilesList里调用了很多setTileEnabled,然后会进入到SettingsDrawerActivity的setTileEnabled。
从两处代码可以看出,可以控制某个Item是否显示在UI上。举个栗子,如果我不想让Wi-Fi显示出来,就把下面高亮部分替换成false就行了。
SettingsDrawerActivity的setTileEnabled的最后调用了onCategoriesChanged。
这个mCategoryListeners是在哪赋值的呢? 是在DashboardSummary的onStart里。这样就会调用DashboardSummary里的onCategoriesChanged。
onCategoriesChanged里直接调用了rebuildUI,相当于settings界面又刷新了一次。
Settings界面显示出来了,当我们进入到某个Item时是什么个流程呢?
之前说了DashboardAdapter的onBindViewHolder:
很明显,我们要去看看DashboardAdapter的onClick。
会进入到第一个if里,调用SettingsDrawerActivity的openTitle。
这里的tile.intent我们前面已经得到了的,里面有ActivityInfo的packageName和name,这里就是打开对应的activity了。
比如我进入Display就是启动了Settings类里面的DisplaySettingsActivity。
这样我们又会调用SettingsActivity的onCreate。这次的流程就和第一次进入Settings界面有点不一样了。
这次mFragmentClass有值了,mIsShowingDashboard为false了!这次会得到当前activity对应的Fragment
(Display对应的就是”com.android.settings.DisplaySettings“),显示这个Fragment的内容。具体内容我没往下看,讲不出来,抱歉!
onCreate执行完之后,还是会调用doUpdateTilesList。最开始我很困惑,为什么每次进入到Item都会调用这个函数,
而且UI上显现的内容与这个函数里的控制的内容毫不关系呢。后来才知道只有Settings主界面对应的DashboardSummary
调用了addCategoryListener。也就是说doUpdateTilesList这次调用没鸟用。
到此结束。