前言
Camera APP的系统设置模块是经过精心设计的一套流程。
该套流程在初次接触的过程中会感觉有些复杂,在此对其初始化的过程进行分析。
该套流程在初次接触的过程中会感觉有些复杂,在此对其初始化的过程进行分析。
入口
void com.android.camera.Camera.initializeCameraPreferences()该方法最终生成一个PreferenceGroup对象,保存在com.android.camera.Camera的属性mPreferenceGroup中。
调用位置
Referenced by com.android.camera.Camera.CameraStartUpThread.run().在每次对硬件Camera打开后调用。
相关类及方法
preferences的初始化过程涉及到对以下类进行初始化
- PreferenceGroup
- ListPrefernece(IconListPreference)
- ComboPreferences
- SettingChecker
了解上述类
这一节对上述类中的属性进行介绍。所谓初始化就是对这些属性初始化。CameraPreference
抽象类,定义了接口OnPreferenceChangedListener,定义了方法getSharedPreferences(),该方法通过调用ComboPreferences.get()取得SharedPreferences。
PreferenceGroup
继承自CameraPreference。定义了属性ArrayList<CameraPreference> list。定义了方法findPreference(key)用于从list中取得key对应的ListPreference,该方法可以从PreferenceGroup中通过递归获得ListPreferenceListPreference
承自CameraPreference。理解ListPreference是了解整个初始化过程的关键。
- 定义了三组entries,entryValues数组。
这三组数组的关系,用集合表示如下图
与这三组数组相关方法及转换过程如下图
- getValue()
通过getSharedPreferences()取得key value;(ComboPreferences)
- proetected persistStringValue()
该方法封装在setValue()中,负责写入key value(ComboPreferences)
IconListPreference
继承自ListPreference,为每个属性增加了图标,增加了对图标的操作。该类及子类此处不做深入了解。初始化过程参照ListPreferenceComboPreferences
保存APP自定义的global,local SharedPreferencesSettingChecker
SettingChecker控制setting界面中选项的位置,状态。定义了一张表mListPrefs[],表中条目为setting界面的选项。
初始化过程
Camera_preferences.xml
定义了PreferenceGroup,其中的成员是ListPreference,IconListPreference。每个成员定义了defaultValue,entries,entryValues,icons,key,title
CameraSetting.getPreferenceGroup()
该方法通过PreferenceInflater对象的inflate方法, 解析Camera_preferences.xml文件,将CameraPreference,ListPreference,IconListPreference通过反射机制生成具体对象。CameraSettings.initPreference()
作用
初始化SettingChecker.mListPrefs[]。使得PreferenceGroup中每一个ListPreferene都映射mListPrefs中一项。最终结果如下图
过程
多数设置项的处理流程相似,只是某些项想有单独的处理方式。把握住上面的Entries关系图就能基本清楚。
- 先通过settingChecker.clearListPreference()清空该数组。
- 不需要进行supported检查的pref,通过settingChecker.setListPreference(int row, ListPreference pref);将PreferenceGroup.list[]中保存的引用赋值给mListPrefs[]。
- 需要进行检查的pref,调用filterUnsupportedOptions(),mParameters.getSupportedXXX(),ListPreferene.filterUnsupported(),将mOriginalEntries,mOriginalEntryValues中supported的值保存到mEntries,mEntryValues,mOriginalSupportedEntries,mOriginalSupportedEntryValues。参见上面Entries关系图。最后将将PreferenceGroup.list[]中保存的引用赋值给mListPrefs[]。
- 上一步中,如果mOriginalSupportedEntries是空串,则调用removePreference(),将该pref从PreferenceGroup中移除(group.removePreference(i);),将mListPrefs这一项的值设为null(CameraSetting.removePreference(int row))
其他情况
- 录像的品质是MTK自己设定的,所以使用getMTKSupportedVideoQuality()替代mParameters.getSupportedXXX()
- filter picture size 会先根据mParameters.getSupportedPictureSizes(),再根据pictureRatio构建出的supportedForRatio,前后两次来设置ListPreference。两次filter的流程与基本流程一致。
- FeatureSwitcher.isXXXenabled()是MTK用来标记某些功能是否打开。
SettingChecker.filterUnsuportedPreference()
源代码中注释:
//CameraSetting.initPreference() will filter some preference according to native Parameter //Unluckily, not all item are set by camera server, here we correct these lost items.
这段注释描述了CameraSetting.initPreference()的作用,也表示filterUnsuportedPreference()是对其补充。
该方法根据二维静态数组static SettingChecker.MATRIX_SETTING_VISIBLE[][](前后摄像头各一个维度),决定该pref是否显示出来。如果不显示,则将该pref从PreferenceGroup,SettingChecker.mListPrefs[]中移除。
初始化结束
发送消息MSG_CAMERA_PREFERENCE_READY,notifyPreferenceReady()让监听者更新与preference相关的属性.设计
public ComboPreferences getPreferences() { //not recommended return mPreferences; } public PreferenceGroup getPreferenceGroup() { //not recommended return mPreferenceGroup; } public ListPreference getListPreference(int row) { return mSettingChecker.getListPreference(row); }
- 附上的源代码可以看到,直接获取ComboPreferences,PreferenceGroup 是不被推荐的,mSettingChecker是获得ListPreference,修改Preference的接口。
- ListPreference中的getValue(),setValue()可以保证ListPreference,ComboPreferences同时更新。
- 源码中只有SettingChecker会调用getPreferences()