改Setting的主菜单的一个显示问题,发现android原生的Settings 在7.0 发生了很大的变化。
主要有:
1、增加了侧滑菜单;
2、增加了Suggestions
3、可以在主界面显示状态(这篇博客主要针对这个)
4、主界面使用RecyclerView

这个是主界面加载的时序图

本文主要介绍下 Summary的显示流程

通过搜索可以定位到这个配置的地方是在 下面代码加粗的地方配置

 public void setListening(boolean listening) {            if (listening) {                // TODO: Listen.                BatteryInfo.getBatteryInfo(mContext, new BatteryInfo.Callback() {                    @Override                    public void onBatteryInfoLoaded(BatteryInfo info) {                        *mLoader.setSummary(SummaryProvider.this, "("+(int)BatteryCapcityValue+"mAh)"+info.mChargeLabelString);*                    }                });            }        }

知其然要知其所以然 所以今天分析下为什么一个Summary 需要在这个地方配置。
进入setSummary 方法

public void setSummary(SummaryProvider provider, final CharSequence summary) {        final ComponentName component= mSummaryMap.get(provider);        mHandler.post(new Runnable() {            @Override            public void run() {                // Since tiles are not always cached (like on locale change for instance),                // we need to always get the latest one.                Tile tile = mAdapter.getTile(component);                if (tile == null) return;                if (DEBUG) Log.d(TAG, "setSummary " + tile.title + " - " + summary);                tile.summary = summary;                mAdapter.notifyChanged(tile);            }        });    }

可以发现主要就是设置titile的summary 然后通知Adapter更新,而Adapter 是DashboardAdapter的实例,是设置给DashboardSummary的,通过上面的时序图其实可以Settings的布局其实就是在DashboardSummary中进行处理的。

而mLoader.setSummary(SummaryProvider.this, “(“+(int)BatteryCapcityValue+”mAh)”+info.mChargeLabelString);又是在什么时候调用的呢
通过时序图可以发现在DashboardSummary中的oncreate中

 public void onCreate(Bundle savedInstanceState) {        long startTime = System.currentTimeMillis();        super.onCreate(savedInstanceState);        List categories =                ((SettingsActivity) getActivity()).getDashboardCategories();        **mSummaryLoader = new SummaryLoader(getActivity(), categories);**        setHasOptionsMenu(true);        Context context = getContext();        mConditionManager = ConditionManager.get(context, false);        mSuggestionParser = new SuggestionParser(context,                context.getSharedPreferences(SUGGESTIONS, 0), R.xml.suggestion_ordering);        mSuggestionsChecks = new SuggestionsChecks(getContext());        if (DEBUG_TIMING) Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime)                + " ms");    }

会new一个SummaryLoader 它的构造方法主要做了这几件事:
1、创建一个Handler对象;
2、创建异步线程;
3、利用双重循环遍历每个title,然后通过异步线程处理各个tile;

 public SummaryLoader(Activity activity, List categories) {        mHandler = new Handler();        mWorkerThread = new HandlerThread("SummaryLoader", Process.THREAD_PRIORITY_BACKGROUND);        mWorkerThread.start();        mWorker = new Worker(mWorkerThread.getLooper());        mActivity = activity;        for (int i = 0; i < categories.size(); i++) {            List tiles = categories.get(i).tiles;            for (int j = 0; j < tiles.size(); j++) {                Tile tile = tiles.get(j);                mWorker.obtainMessage(Worker.MSG_GET_PROVIDER, tile).sendToTarget();            }        }    } private synchronized void makeProviderW(Tile tile) {        SummaryProvider provider = getSummaryProvider(tile);        if (provider != null) {            if (DEBUG) Log.d(TAG, "Creating " + tile);            mSummaryMap.put(provider, tile.intent.getComponent());        }    }

可以发现最后把 SummaryProvider和 Component已键值对的形式放到了一个ArrayMap中。
这里关键看下getSummaryProvider的实现

 private SummaryProvider getSummaryProvider(Tile tile) {        if (!mActivity.getPackageName().equals(tile.intent.getComponent().getPackageName())) {            // Not within Settings, can't load Summary directly.            // TODO: Load summary indirectly.            // return null;            /// M: support external app dynamic summary            return ExternalSummaryProvider.createExternalSummaryProvider(mActivity, this, tile);        }        Bundle metaData = getMetaData(tile);        if (metaData == null) {            if (DEBUG) Log.d(TAG, "No metadata specified for " + tile.intent.getComponent());            return null;        }        String clsName = metaData.getString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS);        if (clsName == null) {            if (DEBUG) Log.d(TAG, "No fragment specified for " + tile.intent.getComponent());            return null;        }        try {            Class<?> cls = Class.forName(clsName);            Field field = cls.getField(SUMMARY_PROVIDER_FACTORY);            SummaryProviderFactory factory = (SummaryProviderFactory) field.get(null);            return factory.createSummaryProvider(mActivity, this);        } catch (ClassNotFoundException e) {            if (DEBUG) Log.d(TAG, "Couldn't find " + clsName, e);        } catch (NoSuchFieldException e) {            if (DEBUG) Log.d(TAG, "Couldn't find " + SUMMARY_PROVIDER_FACTORY, e);        } catch (ClassCastException e) {            if (DEBUG) Log.d(TAG, "Couldn't cast " + SUMMARY_PROVIDER_FACTORY, e);        } catch (IllegalAccessException e) {            if (DEBUG) Log.d(TAG, "Couldn't get " + SUMMARY_PROVIDER_FACTORY, e);        }        return null;    }

这个方法主要做了以下几件事:
1、获取MetaData;
2、获取MetaData的的META_DATA_KEY_FRAGMENT_CLASS值的值
3、根据上一步获取的字符串 通过反射来获取这个类(上一步获取的字符串形式就是“com.android.settings.fuelgauge.PowerUsageSummary” 这样的)
4、通过上步获取的类获取类中的SUMMARY_PROVIDER_FACTORY这个属性
5、返回类中的SummaryProvider对象。

看第三步可以知道这里获取的就是主界面的各个选项,这里以PowerUsageSummary为例进去看下

public class PowerUsageSummary extends PowerUsageBase {...private static class SummaryProvider implements SummaryLoader.SummaryProvider {        private final Context mContext;        private final SummaryLoader mLoader;        private SummaryProvider(Context context, SummaryLoader loader) {            mContext = context;            mLoader = loader;        }        @Override        public void setListening(boolean listening) {            if (listening) {                // TODO: Listen.                BatteryInfo.getBatteryInfo(mContext, new BatteryInfo.Callback() {                    @Override                    public void onBatteryInfoLoaded(BatteryInfo info) {                        mLoader.setSummary(SummaryProvider.this, "("+(int)BatteryCapcityValue+"mAh)"+info.mChargeLabelString);//add by linyu.li for battery show 20170724                    }                });            }        }    }    public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY            = new SummaryLoader.SummaryProviderFactory() {        @Override        public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,                                                                   SummaryLoader summaryLoader) {            return new SummaryProvider(activity, summaryLoader);        }    };}

所以主界面的每个选项都必须要实现SummaryProvider 和SummaryLoader.SummaryProviderFactory这两个类才能正确的显示Summary

参考文章:http://blog.csdn.net/a771642/article/details/70284335

更多相关文章

  1. android悬浮按钮(Floating action button)的两种实现方法
  2. Android的界面提醒之对话框Dialog
  3. android adb启动失败问题 adb server is out of date. killing..
  4. 学习Android界面设计的超级利器HierarchyView.bat
  5. Android上webview界面切换动画效果
  6. 启动一个没有界面的Activity
  7. Android(安卓)手机小闹钟
  8. Android(安卓)实战 (一) Remote Service,Thread,Handler,Broadcast
  9. Android源码repo init及repo sync小记

随机推荐

  1. js中常见的操作
  2. Python和Visual Studio需要安装Node.js模
  3. 在javascript中使用onclick在使用onclick
  4. 如何在HTML选择选项列表中保留空间hi
  5. VS2010常用插件介绍之Javascript插件
  6. 将JavaScript对象转换为要插入关系数据库
  7. 使用javascript访问网格内的文本框
  8. 单击元素后的load()特定href
  9. 简单数据的最佳服务器端数据存储方法
  10. 如何在jquery galleria中滑动包含内部元