玖叶教程网

前端编程开发入门

Android面试一天一题(7)——正确使用Context

Context在Android开发中无处不在,很多时候我们都是随便拿来用,只要不报错就行,但是当我们考虑到APP的性能时,就要求我们必须正确使用各种Context。

1.Context的作用

首先,我们知道,Context可以用来实现很多功能的调用,比如:

//获取资源管理器对象,进而可以访问到例如string,color等资源

Resources res = context.getResources();

//启动指定Activity

context.startActivity(new Intent(this,MainActivity.class));

//获取各种系统服务

TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHOMY_SERVICE);

//获取系统文件目录

File internalDir = context.getCacheDir();

由此可见,正确使用Context非常重要,在具体问题上需要区别对待,否则很可能会引入各种问题。接下来,我们来看看Context具体有哪些种类。

2.Context种类

根据Context依托的组件以及用途不同,可以将Context分为如下几种。

  • Application:Android应用中的默认单例类,在Activity或者Service中通过getApplication()可以获得这个单例,通过context.getApplicationContext()可以获得应用全局唯一的Context实例。

  • Activity/Service:这两个类都是ContextWrapper的自雷,在这两个类中可以通过getBaseContext()获取到它们的Context实例,不同的Activity或者Service实例,它们的Context都是独立的。

  • BroadcastReceiver:和Activity以及Service不同,BroadcastReceiver本身并不是Context的子类,二是在回调函数onReceive()中由Android框架传入一个Context的实例。系统传入的这个context实例是经过功能裁剪的,它不能调用registerReceiver()以及bindService()这两个函数。

  • ContentProvider:同样,ContentProvider也不是Context的自雷,但在创建时系统会传入一个Context实例,这样在ContentProvider中可以通过调用getContext()函数获取。如果ContentProvider和调用者处于相同的应用进程中,那么getContext()将反馈应用全局唯一的Context实例。如果是其他进程调用的ContentProvider,那么ContentProvider将持有自身所在进程的Context实例。

3.错误使用Context导致内存泄露

错误地使用Context可能会导致内存泄露,典型的例子是在实现单例模式时使用Context,如下所示:

public class SingleInstance{

private Context context;

private static SingleInstance instance;

private SingleInstance(Context context){

context = context;

}

public static SingleInstance getInstance(Context context){

if(instance == null){

instance = new SingleInstance(context);

}

return instance;

}

}

如果使用者调用getInstance时传入的Context是一个Activity或者Service的实例,那么在应用退出前,由于单例一直存在,会导致对应的Activity或者Service被单例引用,从而不会被垃圾回收,Activity或者Service中关联的其他View或者数据结构对象也不会被释放,从而导致内存泄露。正确的做法是使用Application Context,因为它是应用唯一的,而且生命周期是跟应用一样的,正确的单例实现如下:

public class SingleInstance{

private Context context;

private static SingleInstance instance;

private static SingleInstance getInstance(Context context){

if(instance==null){

instance = new SingleInstance(context.getApplicationContext());

}

return instance;

}

}

3.不同Context的对比

不同组件中的Context能提供的功能不尽相同,我这里将它总结在下表中。

context各功能总结

其中NO1表示对应的组件并不是真的不可以启动Activity,而是建议不要这么做,因为这些组件会在新的Task中创建Activity,而不是在原来的Task中。

NO2也表示不建议这么做,因为在非Activity中进行Layout Inflation,会使用系统默认的主题,而不是应用中设置的主题。

NO3表示在Android4.2及以上的系统上,如果注册的BroadcastReceiver是null时是可以的,用来获取sticky广播的当前值。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言