PGzxc的博客

纸上得来终觉浅 绝知此事要躬行

0%

Android开发之——Context你必须知道的一些事

作为开发者,对于Context的使用一定不陌生;你在加载资源、启动一个新的Activity、获取系统服务、获取内部文件(夹)路径、创建View操作时等都需要Context的参与,可见Context的常见性;

什么是Context上下文

  • Context
    字面意思上下文,或者叫做场景,也就是用户与操作系统操作的一个过程,比如你打电话,场景包括电话程序对应的界面,以及隐藏在背后的数据
  • 源码中的Context
    源码

一个应用程序有几个Context

Context数量=Activity数量+Service数量+1(Application)

Context能干什么

弹出Toast、启动Activity、启动Service、发送广播、操作数据库等等

Context作用域

作用域

如何获取Context

  • View.getContext,返回当前View对象的Context对象,通常是当前正在展示的Activity对象
  • Activity.getApplicationContext,获取当前Activity所在的(应用)进程的Context对象,通常我们使用Context对象时,要优先考虑这个全局的进程Context
  • ContextWrapper.getBaseContext():用来获取一个ContextWrapper进行装饰之前的Context,可以使用这个方法,这个方法在实际开发中使用并不多,也不建议使用
  • Activity.this 返回当前的Activity实例,如果是UI控件需要使用Activity作为Context对象,但是默认的Toast实际上使用ApplicationContext也可以

Context引起的内存泄露

  • 错误的单例模式

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

    这是一个非线程安全的单例模式,instance作为静态对象,其生命周期要长于普通的对象,其中也包含Activity,假如Activity A去getInstance获得instance对象,传入this,常驻内存的Singleton保存了你传入的Activity A对象,并一直持有,即使Activity被销毁掉,但因为它的引用还存在于一个Singleton中,就不可能被GC掉,这样就导致了内存泄漏

  • 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掉,所以造成内存泄漏。

正确使用Context

  • 当Application的Context能搞定的情况下,并且生命周期长的对象,优先使用Application的Contex
  • 不要让生命周期长于Activity的对象持有到Activity的引用
  • 量不要在Activity中使用非静态内部类,因为非静态内部类会隐式持有外部类实例的引用,如果使用静态内部类,将外部实例引用作为弱引用持有

参考:
Android Context 上下文 你必须知道的一切
Context都没弄明白,还怎么做Android开发?