Setting学习(三)-数据加载之一级菜单

Posted by DoubleWay on February 3, 2020

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
DashboardFeatureProvider的具体实现类是DashboardFeatureProviderImpl

然后执行:

packages\apps\settings\src\com\android\settings\dashboard\SummaryLoader.java

其传入的参数为 当前的activity 以及 CategoryKey.CATEGORY_HOMEPAGE字串

可以看到Category,类别对象是通过DashboardFeatureProviderImpl的getTilesForCategory方法,因为DashboardFeatureProviderImpl是mDashboardFeatureProvider的实现

packages\apps\settings\src\com\android\settings\dashboard\DashboardFeatureProviderImpl.java

DashboardFeatureProviderImpl:

mCategoryManager的初始化时在DashboardFeatureProviderImpl的构造方法中,使用CategoryManager的静态方法get获取的:

frameworks\base\packages\settingslib\src\com\android\settingslib\drawer\CategoryManager.java

其构造方法初始化一些参数,再看CategoryManager的getTilesByCategory方法:

然后调用了tryInitCategories方法:

由于是第一次进入,mCategories并没有初始化过,因此会走入if条件,然后调用TileUtils.java的getCategories方法,初始化mCategories的数据,注意传入的参数为 context

frameworks\base\packages\settingslib\src\com\android\settingslib\drawer\TileUtils.java

现在来详细看看getCategories方法:

  1. 首先调用调用了getTilesForAction()方法
  1. 调用getTilesForIntent方法
  1. getTilesForIntent中调用updateTileData方法:
解析meta-data标签,获得name为META_DATA_PREFERENCE_ICON的value值赋给icon
解析meta-data标签 获取name为 META_DATA_PREFERENCE_TITLE的resource值赋值给title
如果title为空就获取acitvity标签label属性赋值给title
如果icon等于0就获取acitvity标签icon属性赋值给icon
  1. getTilesForIntent中调用addedCache.put(key, tile)方法
  1. 回到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。 数据获取到以后开始返回,到这里为止,整个数据获取的流程已经清楚,但是数据加载是在哪里完成的呢,首先还要回到SettingsDrawerActivity的onResume()方法中,可以看到:

除了注册了一个广播接收器,还执行了一个异步操作: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之后才会生效。