欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android M Settings界面加载流程分析

程序员文章站 2022-05-23 19:57:17
...

StartUML简易分析

Android M Settings界面加载流程分析

 


代码分析:

从Setting-AndroidManifest开始

<application android:label="@string/settings_label"

            android:icon="@mipmap/ic_launcher_settings"

            android:taskAffinity=""

            android:theme="@style/Theme.Settings"

            android:hardwareAccelerated="true"

            android:requiredForAllUsers="true"

            android:supportsRtl="true"

            android:allowBackup="false"

            android:usesCleartextTraffic="true">

        <!-- Settings -->

        <activity android:name="Settings"

                android:taskAffinity="com.android.settings"

                android:label="@string/settings_label_launcher"

                android:launchMode="singleTask">

            <intent-filter android:priority="1">

                <action android:name="android.settings.SETTINGS" />

                <category android:name="android.intent.category.DEFAULT" />

            </intent-filter>

            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"

                android:value="true" />

        </activity>

可以看出是从Settings开始加载


Settings继承自SettingsActivity

public class Settings extends SettingsActivity {

    /*

    * Settings subclasses for launching independently.

    */

    public static class BluetoothSettingsActivity extends SettingsActivity { /* empty */ }

    public static class WirelessSettingsActivity extends SettingsActivity { /* empty */ }

    public static class SimSettingsActivity extends SettingsActivity { /* empty */ }

    public static class TetherSettingsActivity extends SettingsActivity { /* empty */ }

    public static class VpnSettingsActivity extends SettingsActivity { /* empty */ }

    public static class DateTimeSettingsActivity extends SettingsActivity { /* empty */ }

    public static class StorageSettingsActivity extends SettingsActivity { /* empty */ }

    public static class PrivateVolumeForgetActivity extends SettingsActivity { /* empty */ }

    public static class PrivateVolumeSettingsActivity extends SettingsActivity { /* empty */ }

    public static class PublicVolumeSettingsActivity extends SettingsActivity { /* empty */ }

    public static class WifiSettingsActivity extends SettingsActivity { /* empty */ }

    public static class WifiP2pSettingsActivity extends SettingsActivity { /* empty */ }

    public static class InputMethodAndLanguageSettingsActivity extends SettingsActivity { /* empty */ }


public class SettingsActivity extends Activity

        implements PreferenceManager.OnPreferenceTreeClickListener,

        PreferenceFragment.OnPreferenceStartFragmentCallback,

        ButtonBarHandler, FragmentManager.OnBackStackChangedListener,

        SearchView.OnQueryTextListener, SearchView.OnCloseListener,

        MenuItem.OnActionExpandListener {

...

@Override

    protected void onCreate(Bundle savedState) {

        super.onCreate(savedState);

        // Should happen before any call to getIntent()

        getMetaData();

        ......

    }




//初始化第一步获取数据

    /**

     * 如获得数据成功,

     * 则表示不是直接启动设置的(比较启动的是:BluetoothSettingsActivity),

     * 则不会显示所有的设置项,只显示具体的设置项(比较蓝牙设置)。

     */

    private void getMetaData() {

        try {

            ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),

                    PackageManager.GET_META_DATA);

            if (ai == null || ai.metaData == null) return;

            mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);

        } catch (NameNotFoundException nnfe) {

            // No recovery

            Log.d(LOG_TAG, "Cannot get Metadata for: " + getComponentName().toString());

        }

    }


可以看出第一步先是进行了fragment的判断--接着onCreate其他函数往下看

...

//判断当前的类是哪个具体的类

        mIsShowingDashboard = className.equals(Settings.class.getName());


 // This is a "Sub Settings" when:

        // - this is a real SubSettings

        // - or :settings:show_fragment_as_subsetting is passed to the Intent

        //如果是通过点击桌面的设置进入,那么mIsShowingDashboard的值就为真。

        final boolean isSubSettings = this instanceof SubSettings ||

                intent.getBooleanExtra(EXTRA_SHOW_FRAGMENT_AS_SUBSETTING, false);

....

//设置进入的模块

        setContentView(mIsShowingDashboard ?

                R.layout.settings_main_dashboard : R.layout.settings_main_prefs);

....

        if (savedState != null) {

           ....

            }

         ....

        } else {

            if ((initialFragmentName != null) && !mIsShowingDashboard) {

               ....

            } else {

              //加载片段

                // No UP affordance if we are displaying the main Dashboard

                mDisplayHomeAsUpEnabled = false;

                // Show Search affordance

                mDisplaySearch = true;

                mInitialTitleResId = R.string.dashboard_title;

                /**

                 * switchToFragment()方法,目的是切换到对应的片段上(帧布局起作用了吧^ _ ^),

                 * 也就是DashboardSummary这个片段。

                 * 接下来看一下DashboardSummary.java这个类了。

                 */

                switchToFragment(DashboardSummary.class.getName(), null, false, false,

                        mInitialTitleResId, mInitialTitle, false);

            }

        }

 

关键方法...进行了Fragment界面加载-->跳转到DashboardSummary.class查看


根据上诉代码分析...大致布局可以理解为如下

 

Android M Settings界面加载流程分析

 

---实际调用了的布局自上而下依次是---

R.layout.settings_main_dashboard

R.layout.dashboard

R.layout.dashboard_category

DashboardTile--framelayout


根据如上分析--大致如下

switchToFragment(DashboardSummary.class.getName(), null, false, false,

                        mInitialTitleResId, mInitialTitle, false);


public class DashboardSummary extends InstrumentedFragment 


    @Override

    public View onCreateView(LayoutInflater inflater, ViewGroup container,

                             Bundle savedInstanceState) {

        mLayoutInflater = inflater;

    //加载布局

        final View rootView = inflater.inflate(R.layout.dashboard, container, false);

        mDashboard = (ViewGroup) rootView.findViewById(R.id.dashboard_container);

        return rootView;

    }

紧接着查看onResume方法

    @Override

    public void onResume() {

        super.onResume();

      //显示各个设置的选项

        sendRebuildUI();

        final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);

        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);

        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);

        filter.addAction(Intent.ACTION_PACKAGE_REPLACED);

        filter.addDataScheme("package");

        getActivity().registerReceiver(mHomePackageReceiver, filter);

    }

private void sendRebuildUI() {

        if (!mHandler.hasMessages(MSG_REBUILD_UI)) {

            mHandler.sendEmptyMessage(MSG_REBUILD_UI);

        }

    }

    private static final int MSG_REBUILD_UI = 1;

    private Handler mHandler = new Handler() {

        @Override

        public void handleMessage(Message msg) {

            switch (msg.what) {

                case MSG_REBUILD_UI: {

                    final Context context = getActivity();

                    rebuildUI(context);

                } break;

            }

        }

    };

下面是布局进行动态加在的方法

private void rebuildUI(Context context) {

        if (!isAdded()) {

            Log.w(LOG_TAG, "Cannot build the DashboardSummary UI yet as the Fragment is not added");

            return;

        }

        long start = System.currentTimeMillis();

        final Resources res = getResources();

        mDashboard.removeAllViews();

       

        //加在UI之前  先加在数据

        List<DashboardCategory> categories =

                ((SettingsActivity) context).getDashboardCategories(true);

        final int count = categories.size();

        for (int n = 0; n < count; n++) {

            DashboardCategory category = categories.get(n);

            //加在每一个需要的类开始了...

            View categoryView = mLayoutInflater.inflate(R.layout.dashboard_category, mDashboard,

                    false);

            TextView categoryLabel = (TextView) categoryView.findViewById(R.id.category_title);

            categoryLabel.setText(category.getTitle(res));

            ViewGroup categoryContent =

                    (ViewGroup) categoryView.findViewById(R.id.category_content);

            final int tilesCount = category.getTilesCount();

            for (int i = 0; i < tilesCount; i++) {

              //动态加在需要的信息

                DashboardTile tile = category.getTile(i);

                DashboardTileView tileView = new DashboardTileView(context);

                updateTileView(context, res, tile, tileView.getImageView(),

                        tileView.getTitleTextView(), tileView.getStatusTextView());

                tileView.setTile(tile);

                categoryContent.addView(tileView);

            }

            // Add the category

            mDashboard.addView(categoryView);

        }

        long delta = System.currentTimeMillis() - start;

        Log.d(LOG_TAG, "rebuildUI took: " + delta + " ms");

    }

中间调用了一次SettingsActivity中解析XML数据的方法

 public List<DashboardCategory> getDashboardCategories(boolean forceRefresh) {

        if (forceRefresh || mCategories.size() == 0) {

          //更新数据--xml解析

            buildDashboardCategories(mCategories);

        }

        return mCategories;

    }

Android M Settings界面加载流程分析

 

 

 

对应ID看对应代码,这样才是最方便的