zoukankan      html  css  js  c++  java
  • 四大组件的context的研究

    看到同事发了一个这个图。大致有点感觉 ,但是理解的不透彻。三个月后。10.14号。等我多做点东西,对这些部件了解深了再来写一个总结吧。

    今天10.14号,交作业了。这个就是安卓四大组件加一个Application可以实现的功能嘛。

    其实呢,上述的这个功能呢,都与context有关。context在哪些地方用到了呢?弹出Toast、弹出dialog,启动Activity、启动Service、发送广播、操作数据库,Inflate布局等等都需要用到Context。context就是实现功能的情景。

    从这个继承关系图中,contextImpl是抽象类context的具体实现类,contextwrapper是包装类,activity,application,service在初始化的时候会创建contextImpl实例实现context功能。所以activity,application,service本身来说就是context。broadcast与contentprovider用到的context是启动他们时传过来的。特殊一点就是,activity继承于ContextThemeWrapper,也是一个包装类,其内部包含了与主题(Theme)相关的接口,这里所说的主题就是指在AndroidManifest.xml中通过android:theme为Application元素或者Activity元素指定的主题。当然,只有Activity才需要主题,Service是不需要主题的,因为Service是没有界面的后台场景,所以Service直接继承于ContextWrapper,Application同理。



    接下来讨论讨论app与service不能做(不推荐)的事情。
    show a dialog 只可以由activity发出。为什么?最直接的谷歌爸爸设置的token的作用。本人也有写 http://www.cnblogs.com/vitabebeauty/p/7125669.html 
    Start Activity  还是理解成不可以做的吧。activity的启动startActivity(),显示启动,隐式启动,都是一个activity启动另一个。就连咱们的安卓系统都可以理解成一个app应用,咱们的用的app的activity都是系统activity startActivity()出来的。在startActivity()中,根据启动模式,将创建/刷新的activity压入activity栈(任务栈)中,而非Activity类型的Context并没有所谓的任务栈,所以待启动的Activity就找不到栈了,这也是为什么不推荐使用Application、service启动Activity的方式。
    Layout Inflaction
    在Application和Service中去layout inflate也是合法的,但是会使用系统默认的主题样式,如果你自定义了某些样式可能不会被使用。所以这种方式也不推荐使用。
    一句话总结:凡是跟UI相关的,都应该使用Activity做为Context来处理;其他的一些操作,Service,Activity,Application等实例都可以,当然了,注意Context引用的持有,防止内存泄漏。(如何防止泄露简言之,引用者要比被引用的context死的早)
     
     


     

    ,有一篇关于ActivityThread与AppliactionTread的文章,很不错,不是吊书袋,看了之后了解更深。

    Android M 5.0,关于ActivityThread和ApplicationThread的解析.

    附上contextWrapper&contextThemeWrapper(增加theme相关功能)的部分相关代码(包装类,实现依靠mBases即contextImplement实现。contextImplement在 attachBaseContext() 方法里创建)

    public class ContextWrapper extends Context {  
        Context mBase;  
          
        /** 
         * Set the base context for this ContextWrapper.  All calls will then be 
         * delegated to the base context.  Throws 
         * IllegalStateException if a base context has already been set. 
         *  
         * @param base The new base context for this wrapper. 
         */  
        protected void attachBaseContext(Context base) {  
            if (mBase != null) {  
                throw new IllegalStateException("Base context already set");  
            }  
            mBase = base;  
        }  
      
        /** 
         * @return the base context as set by the constructor or setBaseContext 
         */  
        public Context getBaseContext() {  
            return mBase;  
        }  
      
        @Override  
        public AssetManager getAssets() {  
            return mBase.getAssets();  
        }  
      
        @Override  
        public Resources getResources() {  
            return mBase.getResources();  
        }  
      
        @Override  
        public ContentResolver getContentResolver() {  
            return mBase.getContentResolver();  
        }  
      
        @Override  
        public Looper getMainLooper() {  
            return mBase.getMainLooper();  
        }  
          
        @Override  
        public Context getApplicationContext() {  
            return mBase.getApplicationContext();  
        }  
      
        @Override  
        public String getPackageName() {  
            return mBase.getPackageName();  
        }  
      
        @Override  
        public void startActivity(Intent intent) {  
            mBase.startActivity(intent);  
        }  
          
        @Override  
        public void sendBroadcast(Intent intent) {  
            mBase.sendBroadcast(intent);  
        }  
      
        @Override  
        public Intent registerReceiver(  
            BroadcastReceiver receiver, IntentFilter filter) {  
            return mBase.registerReceiver(receiver, filter);  
        }  
      
        @Override  
        public void unregisterReceiver(BroadcastReceiver receiver) {  
            mBase.unregisterReceiver(receiver);  
        }  
      
        @Override  
        public ComponentName startService(Intent service) {  
            return mBase.startService(service);  
        }  
      
        @Override  
        public boolean stopService(Intent name) {  
            return mBase.stopService(name);  
        }  
      
        @Override  
        public boolean bindService(Intent service, ServiceConnection conn,  
                int flags) {  
            return mBase.bindService(service, conn, flags);  
        }  
      
        @Override  
        public void unbindService(ServiceConnection conn) {  
            mBase.unbindService(conn);  
        }  
      
        @Override  
        public Object getSystemService(String name) {  
            return mBase.getSystemService(name);  
        }  
      
        ......  
    }  
    public class ContextThemeWrapper extends ContextWrapper {
        private int mThemeResource;
        private Resources.Theme mTheme;
        private LayoutInflater mInflater;
        private Configuration mOverrideConfiguration;
        private Resources mResources;
    
        public ContextThemeWrapper() {
            super(null);
        }
    
        public ContextThemeWrapper(Context base, @StyleRes int themeResId) {
            super(base);
            mThemeResource = themeResId;
        }
    
        public ContextThemeWrapper(Context base, Resources.Theme theme) {
            super(base);
            mTheme = theme;
        }
    
        @Override
        protected void attachBaseContext(Context newBase) {
            super.attachBaseContext(newBase);
        }
    
        /**
         * Call to set an "override configuration" on this context -- this is
         * a configuration that replies one or more values of the standard
         * configuration that is applied to the context.  See
         * {@link Context#createConfigurationContext(Configuration)} for more
         * information.
         *
         * <p>This method can only be called once, and must be called before any
         * calls to {@link #getResources()} are made.
         */
        public void applyOverrideConfiguration(Configuration overrideConfiguration) {
            if (mResources != null) {
                throw new IllegalStateException("getResources() has already been called");
            }
            if (mOverrideConfiguration != null) {
                throw new IllegalStateException("Override configuration has already been set");
            }
            mOverrideConfiguration = new Configuration(overrideConfiguration);
        }
    
        @Override
        public Resources getResources() {
            if (mResources != null) {
                return mResources;
            }
            if (mOverrideConfiguration == null) {
                mResources = super.getResources();
                return mResources;
            } else {
                Context resc = createConfigurationContext(mOverrideConfiguration);
                mResources = resc.getResources();
                return mResources;
            }
        }
        
        @Override
        public void setTheme(int resid) {
            if (mThemeResource != resid) {
                mThemeResource = resid;
                initializeTheme();
            }
        }
        
        /** @hide */
        @Override
        public int getThemeResId() {
            return mThemeResource;
        }
    
        @Override public Resources.Theme getTheme() {
            if (mTheme != null) {
                return mTheme;
            }
    
            mThemeResource = Resources.selectDefaultTheme(mThemeResource,
                    getApplicationInfo().targetSdkVersion);
            initializeTheme();
    
            return mTheme;
        }
    
        @Override public Object getSystemService(String name) {
            if (LAYOUT_INFLATER_SERVICE.equals(name)) {
                if (mInflater == null) {
                    mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
                }
                return mInflater;
            }
            return getBaseContext().getSystemService(name);
        }
        
        /**
         * Called by {@link #setTheme} and {@link #getTheme} to apply a theme
         * resource to the current Theme object.  Can override to change the
         * default (simple) behavior.  This method will not be called in multiple
         * threads simultaneously.
         *
         * @param theme The Theme object being modified.
         * @param resid The theme style resource being applied to <var>theme</var>.
         * @param first Set to true if this is the first time a style is being
         *              applied to <var>theme</var>.
         */
        protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
            theme.applyStyle(resid, true);
        }
    
        private void initializeTheme() {
            final boolean first = mTheme == null;
            if (first) {
                mTheme = getResources().newTheme();
                Resources.Theme theme = getBaseContext().getTheme();
                if (theme != null) {
                    mTheme.setTo(theme);
                }
            }
            onApplyThemeResource(mTheme, mThemeResource, first);
        }
    }
  • 相关阅读:
    Jmter组件执行顺序
    Win7X64位Seleniume+Eclipse+Pydev环境搭建
    软件测试自学指南---从入门到精通(转载)
    Python开发【第四篇】:Python基础之函数
    Python开发【第三篇】:Python基本数据类型
    Python开发【第二篇】:初识Python
    Python开发【第一篇】:目录
    个人作业3——个人总结(Alpha阶段)
    结对编程2——单元测试(201421123040,60,61)
    个人作业2——英语学习APP案例分析
  • 原文地址:https://www.cnblogs.com/vitabebeauty/p/7171335.html
Copyright © 2011-2022 走看看