1. 程式人生 > >Android 5.1 Settings源代碼簡要分析

Android 5.1 Settings源代碼簡要分析

lang oid inpu mini tty 之前 arch 概述 wro

轉載請註明出處,謝謝~http://blog.csdn.net/u011974987/article/details/51004854。

概述:

先聲明:本人工作快兩年了,仍是菜鳥級別的。羞愧啊!曾經遇到好多知識點都沒有記錄下來,感覺挺可惜的。如今有機會接觸Android 源代碼。

我們一個Android組的搞Setting,我認為是得寫得東西。畢竟才接觸。如今僅僅能看一段時間代碼,就先記錄下一些收獲吧,說多了就是淚~本文主要針對L平臺上Settings模塊正常啟動流程做一個簡要分析,並試著分析一下Settings以下某選項的實現。

Setting 簡單介紹

在之前的KK平臺上Settings模塊的第一個Activity名字為Settings,其繼承的是PreferenceActivity,設置的每個選項都是相應的一個Header對象,而且Header對象同意顯示switch控件,button控件,checkbox控件等。

例如以下圖1.1,WLAN和藍牙上使用到了switch開關。但在L上面,WLAN和藍牙的這兩個開關已經去掉了。如圖1.2,在Settings模塊的首個頁面似乎就僅僅是一個普通的Listview,那它用的還是不是Header呢?或者說取而代之的是什麽呢?繼續往下看吧~

技術分享
圖片-1.1
技術分享
圖片-1.2

L Settings 模塊首界面初始化流程

L Settings模塊首界面為Settings。繼承自SettingsActivity,SettingsActivity繼承自Activity。

首先看一下Settings.java代碼能夠發現它沒有重寫不論什麽SettingsActiviy的方法。也沒有添加不論什麽自己的方法,只有添加了很多靜態內部類,如:

/**
 * Top-level Settings activity
 */
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 WifiSettingsActivity extends SettingsActivity { /* empty */ } public static class WifiP2pSettingsActivity extends SettingsActivity { /* empty */ } public static class InputMethodAndLanguageSettingsActivity extends SettingsActivity { /* empty */ } public static class KeyboardLayoutPickerActivity extends SettingsActivity { /* empty */ } public static class InputMethodAndSubtypeEnablerActivity extends SettingsActivity { /* empty */ } public static class VoiceInputSettingsActivity extends SettingsActivity { /* empty */ } public static class SpellCheckersSettingsActivity extends SettingsActivity { /* empty */ } public static class LocalePickerActivity extends SettingsActivity { /* empty */ } public static class UserDictionarySettingsActivity extends SettingsActivity { /* empty */ } public static class HomeSettingsActivity extends SettingsActivity { /* empty */ } ... }

看凝視能夠知道,這些子類是為了啟動特定獨立的Settings選項而創建的,比如在某個應用裏須要設置無線那麽僅僅須要啟動 WirelessSettingsActivity 就能夠了。

所以Settings模塊的啟動流程直接看SettingsActiviy即可了。
1. SettingsActivity.onCreate方法
onCreate方法是Activity的生命周期第一步。看看 SettingsActivity在這裏都做了些什麽?

 // Should happen before any call to getIntent()

     getMetaData();

這種方法用來獲得Activity的額外數據mFragmentClass。假設能夠獲得這個數據。那麽以下會去顯示mFragmentClass相應的Activity。直接啟動Settings模塊不會獲得這個數據。

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

這一步非常重要,由於我們是從Settings這個Activity過來的,所以這裏的 mIsShowingDashboard 為 true 。

         // This is a "Sub Settings" when:

        // - this is a real SubSettings

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

        final boolean isSubSettings = className.equals(SubSettings.class.getName()) ||

                intent.getBooleanExtra(EXTRA_SHOW_FRAGMENT_AS_SUBSETTING, false);

這個推斷非常重要但非常明顯這時isSubSettings的值是fasle,臨時忽略。

  setContentView(mIsShowingDashboard ?

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

前面知道這裏的 mIsShowingDashboard為true,所以這裏使用的布局文件為R.layout.settings_main_dashboard。settings_main_dashboard.xml文件例如以下:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

             android:id="@+id/main_content"

             android:layout_height="match_parent"

             android:layout_width="match_parent"

             android:background="@color/dashboard_background_color"

             />

由於mIsShowingDashboard為true,直接走到以下這段

  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.class.getName(), null, false, false,

                        mInitialTitleResId, mInitialTitle, false);

              }

這裏看到switchToFragment這種方法,能夠知道這裏是要切換DashboardSummary這個Fragment.

接下來就看看DashboardSummary是個什麽玩意?

dashboard中文意思是儀表盤,這裏是指DashboardSummary就是用來顯示Settings全部選項的。

在DashboardSummary的onCreateView裏載入了這個布局文件R.layout.dashboard

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/dashboard"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:scrollbarStyle="outsideOverlay"

    android:clipToPadding="false">



        <LinearLayout

                android:id="@+id/dashboard_container"

                android:layout_width="match_parent"

                android:layout_height="match_parent"

                android:layout_gravity="center_horizontal"

                android:paddingStart="@dimen/dashboard_padding_start"

                android:paddingEnd="@dimen/dashboard_padding_end"

                android:paddingTop="@dimen/dashboard_padding_top"

                android:paddingBottom="@dimen/dashboard_padding_bottom"

                android:orientation="vertical"

                />



</ScrollView>

看了上面的布局文件能夠知道Settings的選項視圖應該就是顯示在dashboard_container中了。



DashboardSummary走完onCreateView方法後會走onResume,然後一路下來又會調到SettingsActivity的

loadCategoriesFromResource(R.xml.dashboard_categories, categories);

這一步是通過 R.xml.dashboard_categories來載入categories,這裏的categorys為ArrayList mCategories。

接著來看看dashboard_categories.xml這個文件吧

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->

<dashboard-categories
        xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- WIRELESS and NETWORKS -->
    <dashboard-category
            android:id="@+id/wireless_section"
            android:title="@string/header_category_wireless_networks" >

        <!-- Wifi -->
        <dashboard-tile
                android:id="@+id/wifi_settings"
                android:title="@string/wifi_settings_title"
                android:fragment="com.android.settings.wifi.WifiSettings"
                android:icon="@drawable/ic_settings_wireless"
                />

        <!--HetComm-->
        <dashboard-tile
                android:id="@+id/hetcomm_settings"
                android:icon="@drawable/ic_settings_hetcomm"
                android:title="@string/hetcom_setting_title">
            <intent android:action="com.android.settings.HETCOMM_SETTINGS" />
        </dashboard-tile>

        <!-- Bluetooth -->
        <dashboard-tile
                android:id="@+id/bluetooth_settings"
                android:title="@string/bluetooth_settings_title"
                android:fragment="com.android.settings.bluetooth.BluetoothSettings"
                android:icon="@drawable/ic_settings_bluetooth2"
                />

        <!-- Hotknot -->
        <dashboard-tile
                android:id="@+id/hotknot_settings"
                android:title="@string/hotknot_settings_title"
                android:fragment="com.mediatek.settings.hotknot.HotKnotSettings"
                android:icon="@drawable/ic_settings_hotknot" 
                />

        <!-- SIM Cards -->
        <dashboard-tile
                android:id="@+id/sim_settings"
                android:title="@string/sim_settings_title"
                android:fragment="com.android.settings.sim.SimSettings"
                android:icon="@drawable/ic_sim_sd"
                />

        <!-- Data Usage -->
        <dashboard-tile
                android:id="@+id/data_usage_settings"
                android:title="@string/data_usage_summary_title"
                android:fragment="com.android.settings.DataUsageSummary"
                android:icon="@drawable/ic_settings_data_usage"
                />

        <!-- Operator hook -->
        <dashboard-tile
                android:id="@+id/operator_settings"
                android:fragment="com.android.settings.WirelessSettings" >
            <intent android:action="com.android.settings.OPERATOR_APPLICATION_SETTING" />
        </dashboard-tile>

        <!-- Other wireless and network controls -->
        <dashboard-tile
                android:id="@+id/wireless_settings"
                android:title="@string/radio_controls_title"
                android:fragment="com.android.settings.WirelessSettings"
                android:icon="@drawable/ic_settings_more"
                />

    </dashboard-category>

    <!-- DEVICE -->
    <dashboard-category
            android:id="@+id/device_section"
            android:title="@string/header_category_device" >

        <!-- Home -->
        <dashboard-tile
                android:id="@+id/home_settings"
                android:title="@string/home_settings"
                android:fragment="com.android.settings.HomeSettings"
                android:icon="@drawable/ic_settings_home"
                />

        <!-- Display -->
        <dashboard-tile
                android:id="@+id/display_settings"
                android:title="@string/display_settings"
                android:fragment="com.android.settings.DisplaySettings"
                android:icon="@drawable/ic_settings_display"
                />

        <!-- Notifications -->
        <dashboard-tile
                android:id="@+id/notification_settings"
                android:title="@string/notification_settings"
                android:fragment="com.mediatek.audioprofile.AudioProfileSettings"
                android:icon="@drawable/ic_settings_notifications"
                />

        <!-- Storage -->
        <dashboard-tile
                android:id="@+id/storage_settings"
                android:title="@string/storage_settings"
                android:fragment="com.android.settings.deviceinfo.Memory"
                android:icon="@drawable/ic_settings_storage"
                />

        <!-- Battery -->
        <dashboard-tile
                android:id="@+id/battery_settings"
                android:title="@string/power_usage_summary_title"
                android:fragment="com.android.settings.fuelgauge.PowerUsageSummary"
                android:icon="@drawable/ic_settings_battery"
                />

        <!-- Application Settings -->
        <dashboard-tile
                android:id="@+id/application_settings"
                android:title="@string/applications_settings"
                android:fragment="com.android.settings.applications.ManageApplications"
                android:icon="@drawable/ic_settings_applications"
                />

        <!-- Manage users -->
        <dashboard-tile
                android:id="@+id/user_settings"
                android:title="@string/user_settings_title"
                android:fragment="com.android.settings.users.UserSettings"
                android:icon="@drawable/ic_settings_multiuser"
                />

        <!-- Manage NFC payment apps -->
        <dashboard-tile
                android:id="@+id/nfc_payment_settings"
                android:title="@string/nfc_payment_settings_title"
                android:fragment="com.android.settings.nfc.PaymentSettings"
                android:icon="@drawable/ic_settings_nfc_payment"
                />

        <!-- Manufacturer hook -->
        <dashboard-tile
                android:id="@+id/manufacturer_settings"
                android:fragment="com.android.settings.WirelessSettings">
            <intent android:action="com.android.settings.MANUFACTURER_APPLICATION_SETTING" />
        </dashboard-tile>

    </dashboard-category>

    <!-- PERSONAL -->
    <dashboard-category
            android:id="@+id/personal_section"
            android:title="@string/header_category_personal" >

        <!-- Location -->
        <dashboard-tile
                android:id="@+id/location_settings"
                android:title="@string/location_settings_title"
                android:fragment="com.android.settings.location.LocationSettings"
                android:icon="@drawable/ic_settings_location"
                />

        <!-- Security -->
        <dashboard-tile
                android:id="@+id/security_settings"
                android:title="@string/security_settings_title"
                android:fragment="com.android.settings.SecuritySettings"
                android:icon="@drawable/ic_settings_security"
                />

        <!-- Account -->
        <dashboard-tile
                android:id="@+id/account_settings"
                android:title="@string/account_settings_title"
                android:fragment="com.android.settings.accounts.AccountSettings"
                android:icon="@drawable/ic_settings_accounts"
                />

        <!-- Language -->
        <dashboard-tile
                android:id="@+id/language_settings"
                android:title="@string/language_settings"
                android:fragment="com.android.settings.inputmethod.InputMethodAndLanguageSettings"
                android:icon="@drawable/ic_settings_language"
                />

        <!-- Backup and reset -->
        <dashboard-tile
                android:id="@+id/privacy_settings"
                android:title="@string/privacy_settings"
                android:fragment="com.android.settings.PrivacySettings"
                android:icon="@drawable/ic_settings_backup"
                />

    </dashboard-category>

    <!-- SYSTEM -->
    <dashboard-category
        android:id="@+id/system_section"
        android:title="@string/header_category_system" >

        <!-- Date & Time -->
        <dashboard-tile
                android:id="@+id/date_time_settings"
                android:title="@string/date_and_time_settings_title"
                android:fragment="com.android.settings.DateTimeSettings"
                android:icon="@drawable/ic_settings_date_time"
                />

        <!--Scheduled power on&off-->
        <dashboard-tile
                android:id="@+id/power_settings"
                android:icon="@drawable/ic_settings_schpwronoff"
                android:title="@string/schedule_power_on_off_settings_title">
            <intent android:action="com.android.settings.SCHEDULE_POWER_ON_OFF_SETTING" />
        </dashboard-tile>

        <!-- Accessibility feedback -->
        <dashboard-tile
                android:id="@+id/accessibility_settings"
                android:title="@string/accessibility_settings"
                android:fragment="com.android.settings.accessibility.AccessibilitySettings"
                android:icon="@drawable/ic_settings_accessibility"
                />

        <!-- Print -->
        <dashboard-tile
                android:id="@+id/print_settings"
                android:title="@string/print_settings"
                android:fragment="com.android.settings.print.PrintSettingsFragment"
                android:icon="@drawable/ic_settings_print"
                />

        <!-- Development -->
        <dashboard-tile
                android:id="@+id/development_settings"
                android:title="@string/development_settings_title"
                android:fragment="com.android.settings.DevelopmentSettings"
                android:icon="@drawable/ic_settings_development"
                />

        <!-- About Device -->
        <dashboard-tile
                android:id="@+id/about_settings"
                android:title="@string/about_settings"
                android:fragment="com.android.settings.DeviceInfoSettings"
                android:icon="@drawable/ic_settings_about"
                />

    </dashboard-category>

</dashboard-categories>

依據這個文件我們能夠知道了,所謂的dashboard就是Settings模塊首界面的一個抽象。而dashboard-categorys則是設置分類集合的抽象,而dashboard-category是分類的抽象,dashboard-tile就是分類下每個選項的抽象了。代碼中的List相應dashboard-categorys, DashboardCategory相應dashboard-category。而dashboard-tile則對因代碼中的DashboardTile。

當載入完這些對象後SettingsActivity會將得到的 mCategories 返回給DashboardSummary來初始化Settings的設置選項。

以下這段代碼就是DashboardSummary.rebuildUI()中完畢界面的初始化

   long start = System.currentTimeMillis();

        final Resources res = getResources();



        mDashboard.removeAllViews();



        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);

        }

這段代碼我就不詳細分析了,邏輯非常easy,遍歷categories這個列表來獲取DashboardCategory對象。將全部DashboardCategory對象和DashboardCategory對象中的DashboardTile對象轉化為視圖對象並加入到主視圖對象mDashboard中。

到這裏SettingsActivity的onCreate方法就算結束了。總結一下,

1.onCreate完畢的任務是切換DashboardSmmary這個Fragment,然後從dashboard_categories.xml中讀取預先配置好的文件來初始化Settings的首界面視圖。
2.L中舍棄了Header類,取而代之的是DashboardCategory和DashboardTile類。

Android 5.1 Settings源代碼簡要分析