点击Settings应用中的恢复出厂设置按钮后流程分析:
先来看onCreateView()方法,这个方法是来加载布局文件的:
接下来再来看establishInitialState()方法,这个方法主要是作为初始化布局控件并未其设置相应的点击事件的作用;
先使用grep命令搜索"恢复出厂设置"字符串,找到相应的布局文件:
packages/apps/Settings/res/xml/privacy_settings.xml
<PreferenceScreen
android:key="factory_reset"
android:title="@string/master_clear_title"
settings:keywords="@string/keywords_factory_data_reset"
android:fragment="com.android.settings.MasterClear" />
在这个节点下我们可以看到这么一句话:
android:fragment="com.android.settings.MasterClear"
这句话表示当点击"恢复出厂设置"这个item后,会直接跳转到MasterClear.java这个Fragment子类内:
先来看onCreateView()方法,这个方法是来加载布局文件的:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (!Process.myUserHandle().isOwner()
|| UserManager.get(getActivity()).hasUserRestriction(
UserManager.DISALLOW_FACTORY_RESET)) {
return inflater.inflate(R.layout.master_clear_disallowed_screen, null);
}
mContentView = inflater.inflate(R.layout.master_clear, null);
establishInitialState();
return mContentView;
}
判断用户是否具有"恢复出厂设置"的权限,根据判断结果来加载布局;由于分析的是"恢复出厂设置"流程,所有直接默认它加载的是master_clear.xml布局。
接下来再来看establishInitialState()方法,这个方法主要是作为初始化布局控件并未其设置相应的点击事件的作用;
/**
* In its initial state, the activity presents a button for the user to
* click in order to initiate a confirmation sequence. This method is
* called from various other points in the code to reset the activity to
* this base state.
*
* <p>Reinflating views from resources is expensive and prevents us from
* caching widget pointers, so we use a single-inflate pattern: we lazy-
* inflate each view, caching all of the widget pointers we'll need at the
* time, then simply reuse the inflated views directly whenever we need
* to change contents.
*/
private void establishInitialState() {
mInitiateButton = (Button) mContentView.findViewById(R.id.initiate_master_clear);
mInitiateButton.setOnClickListener(mInitiateListener);
mExternalStorageContainer = mContentView.findViewById(R.id.erase_external_container);
mExternalStorage = (CheckBox) mContentView.findViewById(R.id.erase_external);
/*
* If the external storage is emulated, it will be erased with a factory
* reset at any rate. There is no need to have a separate option until
* we have a factory reset that only erases some directories and not
* others. Likewise, if it's non-removable storage, it could potentially have been
* encrypted, and will also need to be wiped.
*/
boolean isExtStorageEmulated = false;
StorageHelpUtil mStorageHelpUtil = new StorageHelpUtil();
if (mStorageHelpUtil.getSdCardPath(getActivity()) != null) {
isExtStorageEmulated = true;
}
if (isExtStorageEmulated) {
mExternalStorageContainer.setVisibility(View.VISIBLE);
final View externalOption = mContentView.findViewById(R.id.erase_external_option_text);
externalOption.setVisibility(View.VISIBLE);
final View externalAlsoErased = mContentView.findViewById(R.id.also_erases_external);
externalAlsoErased.setVisibility(View.VISIBLE);
// If it's not emulated, it is on a separate partition but it means we're doing
// a force wipe due to encryption.
mExternalStorage.setChecked(!isExtStorageEmulated);
} else {
mExternalStorageContainer.setVisibility(View.GONE);
final View externalOption = mContentView.findViewById(R.id.erase_external_option_text);
externalOption.setVisibility(View.GONE);
mExternalStorageContainer.setOnClickListener(new View.OnClick