您的位置:首页 > 移动开发 > Android开发

Android5.1 原生应用设置(Settings)主界面启动流程

2015-10-13 11:08 411 查看
别小看Android系统的设置程序,原生的Settings程序居然有10万行代码量,快赶上Kernel V1.0版本的代码量了,之所以这么多代码主要就是设置的功能点非常多非常杂,有的模块也很复杂,有的直接跟整个framework机制或流程有关,所以导致某些bug变成了重量级的问题,难以一时半会看出端倪,需要花费一定的时间去跟踪,比如跟踪系统的语言切换,当初这个bug我也是跟了16个小时,发现要从正面出击解决问题的可能性太小,后来在板型的overlay目录中进行一个覆盖配置,问题得到解决。

废话不多说,直接看代码吧,拿到一个app,肯定是从AndroidManifest.xml入手,因为这里会登记app要求的权限,Receiver监听,Activity或者Service等等,其中写明有android.intent.category.DEFAULT和android.intent.category.LAUNCHER的Activity就是app的入口Activity:

1,./packages/apps/Settings/AndroidManifest.xml

 98         <activity-aliasandroid:name="Settings"

 99                android:taskAffinity="com.android.settings"

100                 android:label="@string/settings_label_launcher"

101                android:launchMode="singleTask"

102                android:targetActivity="Settings">

103            <intent-filter>

104                <action android:name="android.intent.action.MAIN" />

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

106                <category android:name="android.intent.category.LAUNCHER" />

107            </intent-filter>

108        </activity-alias>

 
这里才是真正的入口:
 85         <activity android:name="Settings"

   86                 android:taskAffinity="com.android.settings"

   87                 android:label="@string/settings_label_launcher"

   88                 android:launchMode="singleTask">

   89             <intent-filter>

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

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

   92             </intent-filter>

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

   94                 android:value="true" />

   95         </activity>

 

2,./packages/apps/Settings/src/com/android/settings/Settings.java

24        public class Settings extendsSettingsActivity {  //继承自SettingsActivity

 

 

3,./packages/apps/Settings/src/com/android/settings/SettingsActivity.java

489    @Override

490    protected voidonCreate(Bundle savedState) {

491        super.onCreate(savedState);

563            if (!mIsShowingDashboard) {     

564                // Search is shown we are launched
15576
thru a Settings "shortcut". UPwill be shown

565                // only if it is a sub settings

566                if (mIsShortcut) {

567                    mDisplayHomeAsUpEnabled = isSubSettings;

568                    mDisplaySearch = false;

569                } else if (isSubSettings) {

570                    mDisplayHomeAsUpEnabled = true;

571                    mDisplaySearch = true;

572                } else {

573                    mDisplayHomeAsUpEnabled = false;

574                    mDisplaySearch = false;

575                }

576                setTitleFromIntent(intent);

577

578                  Bundle initialArguments =intent.getBundleExtra(

EXTRA_SHOW_FRAGMENT_ARGUMENTS);

579                switchToFragment(initialFragmentName, initialArguments, true, false,

580                        mInitialTitleResId, mInitialTitle, false);

581            } else {

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

583                mDisplayHomeAsUpEnabled = false;

584                // Show Search affordance

585                mDisplaySearch = true;

586                mInitialTitleResId = R.string.dashboard_title;

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

588                        mInitialTitleResId, mInitialTitle, false);

589          }

 

948      private Fragment switchToFragment(StringfragmentName, Bundle args,

boolean validate, boolean addToBackStack, int titleResId,

CharSequence title, boolean withTransition) {

//利用反射机制实例化DashboardSummary

954               Fragment f = Fragment.instantiate(this,fragmentName, args); 

955               FragmentTransaction transaction =getFragmentManager().beginTransaction();

956               transaction.replace(R.id.main_content,f);

                     。。。

}

 

 R.layout.dashboard是设置的主界面的布局文件,也是设置其他子界面的入口:

4,./packages/apps/Settings/src/com/android/settings/dashboard/DashboardSummary.java

89    public View onCreateView(LayoutInflaterinflater, ViewGroup container,

 90                             Bundle savedInstanceState) {

 92        mLayoutInflater = inflater;

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

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

 97        return rootView;

 98    }

 

68        public voidonResume(){

69                  super.onResume();

71                  sendRebuildUI();

                       。。。

}

 

169      private void sendRebuildUI() {

170               if(!mHandler.hasMessages(MSG_REBUILD_UI)) {

171                         mHandler.sendEmptyMessage(MSG_REBUILD_UI);

172              }

173      }

 

46    private static final int MSG_REBUILD_UI = 1;

47    private Handler mHandler = new Handler() {

49        public void handleMessage(Message msg) {

50            switch (msg.what) {

51                case MSG_REBUILD_UI: {

52                    final Context context = getActivity();

53                    rebuildUI(context);

54                } break;

55            }

56        }

57    };

 

100    private void rebuildUI(Context context) {

106        long start = System.currentTimeMillis();

107        final Resources res = getResources();

108        mDashboard.removeAllViews();

111        List<DashboardCategory> categories = //categories就拥有设置主界面的完整信息

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

                         

//先从R.layout.dashboard_category中找到textview并设置title;

//再找到其中的viewgroup,并用第二层循环实例化categories(i).tilesCount个//DashboardTileView并添加进去

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

117     DashboardCategory category =categories.get(n);

119     View categoryView =mLayoutInflater.inflate(

R.layout.dashboard_category,mDashboard, false);

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

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

 

125     ViewGroup categoryContent =

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

127        finalint tilesCount = category.getTilesCount();

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

130        DashboardTile tile =category.getTile(i);

132        DashboardTileView tileView = newDashboardTileView(context);

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

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

136        tileView.setTile(tile);

138        categoryContent.addView(tileView);

139     }

142     mDashboard.addView(categoryView);

        }

 

4.1,./packages/apps/Settings/src/com/android/settings/SettingsActivity.java

384    public List<DashboardCategory> getDashboardCategories(booleanforceRefresh) {

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

386            buildDashboardCategories(mCategories);

387        }

388        return mCategories;

389    }

 

978    private void buildDashboardCategories(List<DashboardCategory> categories){

979        categories.clear();

 

//dashboard_categories.xml包含的category有无线和网络,设备,个人和系统;

//每个category存储的信息包括title,fragment和icon

980        loadCategoriesFromResource(R.xml.dashboard_categories,categories);

                  

                  //删除过时不用的设置项,比如sim卡设置项,代码太长直接看文件

981        updateTilesList(categories);

982     }

 

 

4.2,./packages/apps/Settings/src/com/android/settings/dashboard/DashboardTileView.java

47    public DashboardTileView(Context context, AttributeSet attrs) {

48     super(context, attrs);

50     final View view = LayoutInflater.from(context).inflate(R.layout.dashboard_tile,this);

52        mImageView = (ImageView) view.findViewById(R.id.icon);

53        mTitleTextView = (TextView) view.findViewById(R.id.title);

54        mStatusTextView = (TextView) view.findViewById(R.id.status);

55        mDivider = view.findViewById(R.id.tile_divider);

57        setOnClickListener(this);

58        setBackgroundResource(R.drawable.dashboard_tile_background);

59        setFocusable(true);

60    }

 

 

4.3,./packages/apps/Settings/src/com/android/settings/dashboard/DashboardSummary.java

148    private void updateTileView(Context context, Resources res,DashboardTile tile,

149            ImageView tileIcon, TextViewtileTextView, TextView statusTextView) {

151        if (tile.iconRes > 0) {

152            tileIcon.setImageResource(tile.iconRes);

153        } else {

154            tileIcon.setImageDrawable(null);

155            tileIcon.setBackground(null);

156        }

157

158        tileTextView.setText(tile.getTitle(res));

159

160        CharSequence summary = tile.getSummary(res);

161        if (!TextUtils.isEmpty(summary)) {

162            statusTextView.setVisibility(View.VISIBLE);

163            statusTextView.setText(summary);

164        } else {

165            statusTextView.setVisibility(View.GONE);

166        }

167    }


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息