Setting模块的界面渲染的时候说过,setting的主界面(一级菜单),是通过DashboardSummary来加载的,DashboardSmmary作为设置主界面的顶部容器,自然与数据的加载也有关。DashboardSummary是Fragment的子类,所以也要执行onCreate()方法:
可以看到在onCreate()方法里面有两个数据提供者mDashboardFeatureProvider,mSuggestionFeatureProvider,这两个是很重要的数据提供者,但是他们两个获取的数据是不同的,这里着重看一下mDashboardFeatureProvider,它提供的数据是一级菜单如”电池”,”显示”,”网络和互联网”等。
FeatureFactory其为单例模式,返回的是FeatureFactoryImpl对象,而FeatureFactoryImpl对象的getDashboardFeatureProvider方法,返回的是DashboardFeatureProviderImpl对象: \packages\apps\settings\src\com\android\settings\overlay\FeatureFactoryImpl.java然后执行:
其传入的参数为 当前的activity 以及 CategoryKey.CATEGORY_HOMEPAGE字串
可以看到Category,类别对象是通过DashboardFeatureProviderImpl的getTilesForCategory方法,因为DashboardFeatureProviderImpl是mDashboardFeatureProvider的实现
packages\apps\settings\src\com\android\settings\dashboard\DashboardFeatureProviderImpl.javaDashboardFeatureProviderImpl:
mCategoryManager的初始化时在DashboardFeatureProviderImpl的构造方法中,使用CategoryManager的静态方法get获取的:
其构造方法初始化一些参数,再看CategoryManager的getTilesByCategory方法:
然后调用了tryInitCategories方法:
由于是第一次进入,mCategories并没有初始化过,因此会走入if条件,然后调用TileUtils.java的getCategories方法,初始化mCategories的数据,注意传入的参数为 context
frameworks\base\packages\settingslib\src\com\android\settingslib\drawer\TileUtils.java现在来详细看看getCategories方法:
- 首先调用调用了getTilesForAction()方法
- 调用getTilesForIntent方法
- getTilesForIntent中调用updateTileData方法:
- getTilesForIntent中调用addedCache.put(key, tile)方法
- 回到getCategories方法,在getTilesForAction方法后执行了createCategory方法
(1)创建DashboardCategory对象
(2)利用PM查询所有含有Tile对象categoriyKey生成的intent对象的ResolveInfo集合
(3)把acitivity label值赋值给category title属性
(4)把解析intent-filter标签的priority值赋值给category属性
通过createCategory方法,创建DashboardCategory,并且根据tile的category来进行分类,最终getCategories方法会返回包含多个DashboardCategory的ArrayList
除了注册了一个广播接收器,还执行了一个异步操作:new CategoriesUpdateTask().execute()
可以看到在异步任务里面除了调用了reloadAllCategories()方法一直加载数据以外,还调用了接口CategoryListener的唯一方法onCategoriesChanged(),那么作为界面容器的DashboardSummary肯定重载了这个接口,实现了onCategoriesChanged()方法,回到DashboardSummary:
在onCategoriesChanged中调用了rebuildUI方法,从注释中可以看到,其实第一次启动时,在DashboardSummary的onViewCreated的方法中也调用了rebuildUI()
onViewCreated的两个作用
1. 初始化DashboardAdapter, 并设置到mDashboard中
2. 重新更新UI
现在就来看看rebuildUI()方法:
在rebuildUI中无论条件判断进入那个分支,都会执行updateCategoryAndSuggestion方法,不论是否支持Suggestion,最终都会调用updateCategoryAndSuggestion方法,并且传入的参数为null
调用DashboardAdapter的setCategory方法,设置获取到的DashboardCategory
最后调用DashboardAdapter的setCategory方法,设置获取到的DashboardCategory
可以知道第一级菜单完全是动态加载的DashboardSummary在onCreateView加载的布局R.layout.dashboard,是一个recycleview
在onViewCreated方法获取到recycleview控件,然后设置获取到的DashboardAdapter
有两种情况,一种是一级菜单是activty,还有一种是一级菜单是fragment
一级菜单项的实现是activity因为是通过activity实现的,通过直接继承activity,实现比较简单 首先,在AndroidManifest.xml清单中添加要添加的菜单项,以HardKey.java为例
然后,再自己实现HardKey.java这个activity,自己实现他的布局和具体逻辑。
一级菜单项的实现是fragment首先也是在AndroidManifest.xml清单中添加:
然后自己实现FlashSettingsActivity.java这个fragment 最后在Setting.java里面添加:
public static class FlashSettingsActivity extends SettingsActivity { /* empty */ } 总结:其实我们添加FlashSettingsActivity这个并不是一个activity,这只是SetttingsActivity的一个子类,而且是空实现,之所以要添加这个空的activity,是为了外部应用能够跳转到FlashSettingsActivity界面,如果是fragment的话,外部应用是无法直接跳转到fragment的,当点击跳转后,会执行SetttingsActivity中的方法,根据其在AndroidManifest清单文件中的注册信息,它的的mata-data信息,找到“com.android.settings.FRAGMENT_CLASS”,然后加载对应的fragment,一般在AndroidManifest中会声明称settings的内部类: android:name=”Settings$FlashSettingsActivity” 在尝试修改priority=”9”会发现,mmm模块编译安装到手机之后发现位置没有改变啊。其实这个priority=”9”的判断是在frameworks中进行处理的,所以只有编译frameworks之后才会生效。