浅析Context在常见类的用法

作用:

虽然本文标题为“浅析Context在常见类的用法”,但阅读者可能有不少是对Context感到疑惑的,故在此附述一下其作用和理解。

在Android中凡是一个带有GUI的组件被调用,必然不是普通Java代码那样直接new一个对象实例即可,而是需要一个特定的环境下才能被显示出来。当然,一些特殊的组件例如Service虽然不是GUI形式,但其特殊在于它可以完成很复杂的任务操作(理解为不带GUI的Activity),当Service被调用然后工作时,其需要一个特定的工作环境才能启动。

一些特殊的组件如Toast和Dialog,虽然不再需要我们额外布局,但当我们调用时它们时,必须有一个特殊的环境,不然可能发生不是我们想要的地方出现,也可能显示错位,当然也可能显示不出来。

上面提到的环境,即为Context。该词中译包括环境语义上下文等。从字面意思来看,上下文,就如同文章里面某一段落一样,某一段落可能是承上启下的作用,没有该段落,下一个段落发生的故事可能出现逻辑上的纰漏。有了完整的上下文,故事便可完整叙述下去且内容逻辑严谨。Android程序也是如此,某个组件缺少了具体的上下文,便会出错(最明显的是可能应用程序直接闪退)。

附加知识:

这里的附加知识仅为提及,对于具体的开发帮助可能不大,但有助于理解Conetxt

1:类图

在这里插入图片描述

2:Context数量计算

Context数量 = Activity数量 + Service数量 + 1
从类图可以看到Context的拥有者仅有ActivityServiceApplication。一个Android应用仅有一个Application,但可以拥有多个Activity和Service。公式中的1就是指一个Android应用的一个Application

Context在常见类的用法:

初学者可能被thisXXXActivity.thisXXXService.thisv.getContext()getActivity()等搞混淆。

这里先要知晓几个关于Application的Context、Activity的Context、Service的Context的概念。在类图里面都看到了Application、Activity、Service都拥有自己的Context。但每个组件的Context并不是随意使用的。而是有具体的条件。

下面看一个关于三个组件之间Conetxt作用域的表格:

作用域ApplicationActivityService
Dialog××
启动活动: (: (
LayoutInflater: (: (
启动服务
启动广播
注册广播

(√ 代表可以,×代表不可以,: (代表不推荐)
从上表可以看到Activity的作用域最大。那是不是可以认为在应用程序里面全用Activity的Context就行了呢?答案肯定不是的,否则Context也不会分为这几种了。但这里总结了几种使用条件,里面涵盖了几乎所有情况,可供参考:

  • 在Activity里面调用控件、启动服务、广播、LayoutInflater创建等:使用某个组件所处的Activity的Context
  • 在Service里面调用控件、启动服务、广播等:使用某个组件所处的Service的Context,GUI控件必须使用Service依附类(依附的Activity)的Context
  • 在非Activity、非Service、非Application(就是某个普通类,可以为适配器或自定义View等)类中:使用某个组件所处的Activity的Context

上面的看完就需要回到本段标题的内容。thisXXXActivity.thisv.getContext()getActivity()这些指的是什么东西?

  • this:指代的是当前类的对象,也就是上下文。当在onCreate()方里面被使用,指的就是当前Acitivity的Context;当在匿名类里面被使用的时候,指的就是匿名类对象而不是匿名类所处的Acitivity的Context
  • XXXActivity.this:指代的就是某个具体的Activity的Context
  • XXXService.this:指代的就是某个具体的Service的Context
  • v.getContext():指代的就是某个View所处的Activity的Context,常见于适配器等
  • getActivity():指代的就是某个被依附类的Context,常见于Fragment等

1:Intent与启动活动

intent常用于启动活动,startActivity()也需Context。一般情况下前者直接调用Activity的Context,具体指明Context对象,后者直接写。
示例:

Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);

但也有其它情况,例如从Fragment跳转到其它Fragment或Activity。则两者均使用getActivity()来获得Context。
示例:

Intent intent = new Intent(getActivity(), SecondActivity.class);
getActivity().startActivity(intent);

建议不要直接写this,很容易出现内存泄漏等问题。具体指明Context对象还有助于理解程序间的调用关系。

2:启动服务

一般调用当前所处活动的上下文,即XXXActivity.this。但也有例外,例如从一个服务启动另一个服务,那就要写成XXXService.this。本质上仍然是调用当前类的上下文。
示例,在活动中启动一个服务:

Intent intent = new Intent(MainActivity.this, TestService.class);
startService(intent);

示例,在碎片中启动一个服务:

Intent intent = new Intent(getActivity(), TestService.class);
getActivity().startService(intent);

示例,在服务中启动一个服务:

Intent intent = new Intent(CurrentService.this, TestService.class);
startService(intent);

3:启动广播

和“启动服务”相同

4:Toast

一般调用Activity的Contextt

示例:

Toast.makeText(MainActivity.this, "Text", Toast.LENGTH_SHORT).show();

5:Dialog

和“Toast”相同

6:RecyclerView

有两种方式,一种是使用v.getContext(),另一种是自定义参数传入Context。但二者本质上都是Activiy的Context。
onBindViewHolder()方法里面如要使用Glide来进行ImageView图片资源的初始化,就必须得到一个Context,那么这个管理该Context的适配器可写成:
示例:

RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(getActivity(), bean);

RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(XXXActivity.this, bean);

上面的情况是只能能使用getActivity()(或直接指明上下文)。其实在onCreateViewHolder()里面中写法都是可以的。

7:Fragment

Fragment调用Acitivity的方法必须使用getActivity()。
示例:

getActivity().finish()

8:LayoutInflater

使用要展示活动的上下文。
示例:

LayoutInflater.from(mContext).inflate(R.layout.list_item, null)

在其初始化时传入要展示活动的上下文即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值