Android Context

Android Context,第1张

概述、Context 概念 从Android系统的角度来理解:Context是一个场景,描述的是一个应用程序环境的信息,即上下文,代表与 *** 作系统的交互的一种过程。 从程序的角度上来理解:Context是个抽象类,而Activity、Service、Application等都是该类的一个实现。 2、Context 继承结构   应用在三种情况下会创建Context对象(即通常说的context):  1 、Context 概念

从AndroID系统的角度来理解:Context是一个场景,描述的是一个应用程序环境的信息,即上下文,代表与 *** 作系统的交互的一种过程。

从程序的角度上来理解:Context是个抽象类,而Activity、Service、Application等都是该类的一个实现。

2、Context 继承结构

 

应用在三种情况下会创建Context对象(即通常说的context): 
1> 创建Application 对象时,即第一次启动app时。 整个App共一个Application对象,(我们只需谨记一点,Application全局只有一个,它本身就已经是单例了)所以也只有一个Application 的Context,Application销毁,它也销毁; 
2> 创建Activity对象时。Activity销毁,它也销毁; 
3> 创建Service对象时。Service销毁,它也销毁。

由此可以得到应用程序App可以创建的Context(Activity和Service没启动就不会创建)个数公式一般为: 
总Context实例个数 = Service个数 + Activity个数 + 1(Application对应的Context对象) 

3、Context 如何获取

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

@H_403_41@
public class MyActivity extends Activity {    Context mContext;    public voID method() {    mContext = this; //获取当前Activity的上下文,如果需要绑定Activity的生命周期,使用它    mContext=MyActivity.this;//获取当前MyActivity的上下文,不方便使用this的时候推荐使用这种方式    //调用Activity.getApplicationContext()    mContext = getApplicationContext();//获取当前Application的上下文,如果需要绑定应用的生命周期,使用它    //Activity.getApplication()    mContext = getApplication();//获取当前Application的上下文,    //调用Contextwrapper.getBaseContext()    mContext = getBaseContext();//从上下文A内上下文访问上下文A,不建议使用,如果需要,推荐使用XxxClass.this直接指出上下文   }}public class MyVIEw extends VIEw {    Context mContext;    public voID method() {    //调用VIEw.getContext()    mContext = getContext(); //获取这个VIEw运行所在地的上下文   }}
3.1 getApplicationContext()和getApplication() getApplicationContext 取得的是当前app所使用的application,这在AndroIDManifest中唯一指定。意味着,在当前app的任意位置使用这个函数得到的是同一个Context,getApplicationContext(): 返回应用的上下文,生命周期是整个应用,应用摧毁,它才摧毁。 getApplication():andorID 开发中共享全局数据;

  getApplication()只能在Activity和Service里使用,指向的是Application对象,因为Application也是Context的一个子类,所以getApplication()可以被用来指向Context。

  比如如果想要获取在应用清单文件中声明的类,最好不要使用getApplicationContext(),并且最好使用强制转换为自己自定义的Application,因为那样可能会得不到Application对象。

@H_403_41@
Log.i("dyl","getApplication is = " + myApp);Log.i("dyl","getApplicationContext is = " + appContext);

通过上面的代码,打印得出两者的内存地址都是相同的,看来它们是同一个对象。其实这个结果也很好理解,因为前面已经说过了,Application本身就是一个Context,所以这里获取getApplicationContext()得到的结果就是Application本身的实例。那么问题来了,既然这两个方法得到的结果都是相同的,那么AndroID为什么要提供两个功能重复的方法呢?实际上这两个方法在作用域上有比较大的区别。getApplication()方法的语义性非常强,一看就知道是用来获取Application实例的,但是这个方法只有在Activity和Service中才能调用的到。那么也许在绝大多数情况下我们都是在Activity或者Service中使用Application的,但是如果在一些其它的场景,比如broadcastReceiver中也想获得Application的实例,这时就可以借助getApplicationContext()方法了

4、Context 使用过程中的注意项

1)Activity mActivity =new Activity()

这样写语法上没有任何错误,AndroID的应用程序开发采用JAVA语言,Activity本质上也是一个对象。但是,

AndroID程序不像Java程序一样,随便创建一个类,写个main()方法就能运行,AndroID应用模型是基于组件的应用设计模式,组件的运行要有一个完整的AndroID工程环境,在这个环境下,Activity、Service等系统组件才能够正常工作,而这些组件并不能采用普通的Java对象创建方式,new一下就能创建实例了,而是要有它们各自的上下文环境,才能使得其正常工作。即走正常的onCreate-onStart-onResume。。。

2)大家在编写一些类时,例如工具类,可能会编写成单例的方式,这些工具类大多需要去访问资源,也就说需要Context的参与。

在这样的情况下,就需要注意Context的引用问题。

@H_403_41@
public class CustomManager  {      private static CustomManager sInstance;      private Context mContext;        private CustomManager(Context context)      {          this.mContext = context;      }        public static synchronized CustomManager getInstance(Context context)      {          if (sInstance == null)          {              sInstance = new CustomManager(context);          }          return sInstance;      }  }

对于上述的单例,大家应该都不陌生(请别计较getInstance的效率问题),内部保持了一个Context的引用;这么写是没有问题的,问题在于,这个Context哪来的我们不能确定,很大的可能性,你在某个Activity里面为了方便,直接传了个this;这样问题就来了,我们的这个类中的sInstance是一个static且强引用的,在其内部引用了一个Activity作为Context,也就是说,我们的这个Activity只要我们的项目活着,就没有办法进行内存回收。而我们的Activity的生命周期肯定没这么长,所以造成了内存泄漏。那么,我们如何才能避免这样的问题呢?有人会说,我们可以软引用,嗯,软引用,假如被回收了,你不怕NullPointException么。把上述代码做下修改:

@H_403_41@
public static synchronized CustomManager getInstance(Context context)  {          if (sInstance == null)          {              sInstance = new CustomManager(context.getApplicationContext());          }          return sInstance;  }

这样,我们就解决了内存泄漏的问题,因为我们引用的是一个ApplicationContext,它的生命周期和我们的单例对象一致。

  3)Intent也要求指出上下文,如果想启动一个新的Activity,就必须在Intent中使用Activity的上下文,这样新启动的Activity才能和当前Activity有关联(在activity栈);也可以使用application的context,但是需要在Intent中添加 Intent.FLAG_ACTIVITY_NEW_TASK标志,当作一个新任务。ApplicationContext去启动一个LaunchMode为standard的Activity的时候会报错,非Activity类型的Context并没有所谓的任务栈,所以待启动的Activity就找不到栈了。解决这个问题的方法就是为待启动的Activity指定FLAG_ACTIVITY_NEW_TASK标记位,这样启动的时候就为它创建一个新的任务栈,而此时Activity是以singleTask模式启动的。所以这种用Application启动Activity的方式不推荐使用,Service同Application。

@H_403_41@
public static voID openActivity(Context context){        Intent intent = new Intent(context.getApplicationContext(),SecondActivity.class);        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        context.getApplicationContext().startActivity(intent);    }
总结

以上是内存溢出为你收集整理的Android Context全部内容,希望文章能够帮你解决Android Context所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1123372.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-30
下一篇 2022-05-30

发表评论

登录后才能评论

评论列表(0条)

保存