Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

Android之Context底层原理

$
0
0

1.Context基本概念

Context的中文翻译为:语境; 上下文; 背景; 环境,在开发中我们经常说称之为“上下文”。从Android系统的角度来理解:Context是一个场景,代表与操作系统的交互的一种过程。Context在加载资源、启动Activity、获取系统服务、创建View等操作都要参与  。从程序的角度上来理解:Context是个抽象类,而Activity、Service、Application等都是该类的一个实现。

2.Context与Activity、Service、Application关系


Context类本身是一个纯abstract类,他有两个具体的实现子类:ContextImpl和ContextWrapper。其中ContextWrapper类,只是一个包装而已,ContextWrapper构造函数中必须包含一个真正的Context引用,同时ContextWrapper提供了attachBaseContext()用于给ContextWrapper对象中指定真正的Context对象,调用ContextWrapper的方法都会被转向其所包含的真正的Context对象。
ContextThemeWrapper类,其内部包含了与主题(Theme)相关的接口,这里所说的主题就是指在AndroidMainifest.xml中通过android:theme为Application元素或者Activity元素指定的主题。当然,只有Activity才需要主题,Service是不需要主题的,Application同理。
而ContextImpl类则真正实现了Context中的所有函数,应用程序中所调用的各种Context类的方法,其实现均来于该类。Context的两个子类分工明确,其中ContextImpl是Context的具体实现类,ContextWrapper是Context的包装类。

3.Context作用域


Activity的作用域最广,Application和Service在启动Activity需要创建一个新的task,一般不推荐。layout infalte也是合法的,但是会使用系统默认的主题样式,如果自定义某些样式可能不会被使用

4.Context的使用

4.1Context的数量

一个应用程序中到底有多少个Context呢?根据Context的类型可以得出,一共有Application、Activity和Service三种类型,因此一个应用程序的Context数量为:
Context数量=Activity数量+Service数量+1

4.2如何获取Context

1)View.getContext,返回当前Activity所在的应用进程的Context对象,通常是当前正在展示的Activity对象
2)Activity.getApplicationContext,获取当前Activity所在的(应用)进程的Context对象,通常我们使用Context对象时,要优先考虑这个全局的进程Context。
3)Activity.this返回当前的Activity实例,如果是UI控件需要使用Activity作为Context对象,但是默认的Toast因为是系统层级的Windows,直接使用ApplicationContext则可。
4)getApplication和getApplicationContext获取的对象时一致的。但是getApplication方法只有在Activity和Service中才能调到。但例如BroadcasrReceiver中需要获取Application,则需要借助getApplicationContext()方法。

4.3Context引起的内测泄漏

1)错误的单例模式
public class Singleton {
    private static Singleton instance;
    private Context mContext;

    private Singleton(Context context) {
        this.mContext = context;
    }

    public static Singleton getInstance(Context context) {
        if (instance == null) {
            instance = new Singleton(context);
        }
        return instance;
    }
}
即使Activity被销毁掉,但因为它的引用还存在于一个Singleton中,就不可能被GC掉
2)View持有Activity引用
public class MainActivity extends Activity {
    private static Drawable mDrawable;

    @Override
    protected void onCreate(Bundle saveInstanceState) {
        super.onCreate(saveInstanceState);
        setContentView(R.layout.activity_main);
        ImageView iv = new ImageView(this);
        mDrawable = getResources().getDrawable(R.drawable.ic_launcher);
        iv.setImageDrawable(mDrawable);
    }
}
有一个静态的Drawable对象当ImageView设置这个Drawable时,ImageView保存了mDrawable的引用,而ImageView传入的this是MainActivity的mContext,因为被static修饰的mDrawable是常驻内存的,MainActivity是它的间接引用,MainActivity被销毁时,也不能被GC掉,所以造成内存泄漏。

5.总结

1)尽量使用Application的Context
2)不要让生命周期长于Activity的对象持有其的引用
3)尽量不要在Activity中使用非静态内部类,因为非静态内部类会隐式持有外部类示例的引用,如果使用静态内部类,将外部实例引用作为弱引用持有

作者:junbin1011 发表于2017/1/19 10:00:32 原文链接
阅读:23 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>