Android Context 上下文 你必须知道的一切

今天被问到了关于Context的一些问题。发现自己关于这部分还是不是很清晰,然后发现洋神博客里有一篇讲的很好 很详细。我反正是看懂了,我觉得我再写 也不会比这个更清楚了,所以转过来。

http://blog.csdn.net/lmj623565791/article/details/40481055,本文出自:【张鸿洋的博客】

1、Context概念

其实一直想写一篇关于Context的文章,但是又怕技术不如而误人子弟,于是参考了些资料,今天准备整理下写出来,如有不足,请指出,参考资料会在醒目地方标明。
Context,相信不管是第一天开发Android,还是开发Android的各种老鸟,对于Context的使用一定不陌生~~你在加载资源、启动一个新的Activity、获取系统服务、获取内部文件(夹)路径、创建View操作时等都需要Context的参与,可见Context的常见性。大家可能会问到底什么是Context,Context字面意思上下文,或者叫做场景,也就是用户与操作系统操作的一个过程,比如你打电话,场景包括电话程序对应的界面,以及隐藏在背后的数据;
但是在程序的角度Context又是什么呢?在程序的角度,我们可以有比较权威的答案,Context是个抽象类,我们可以直接通过看其类结构来说明答案:
这里写图片描述
可以看到Activity、Service、Application都是Context的子类;
也就是说,Android系统的角度来理解:Context是一个场景,代表与操作系统的交互的一种过程。从程序的角度上来理解:Context是个抽象类,而Activity、Service、Application等都是该类的一个实现。
在仔细看一下上图:Activity、Service、Application都是继承自ContextWrapper,而ContextWrapper内部会包含一个base context,由这个base context去实现了绝大多数的方法。
先扯这么多,有能力了会从别的角度去审视Context,加油~

2、Context与ApplicationContext

看了标题,千万不要被误解,ApplicationContext并没有这个类,其实更应该叫做:Activity与Application在作为Context时的区别。嗯,的确是这样的,大家在需要Context的时候,如果是在Activity中,大多直接传个this,当在匿名内部类的时候,因为this不能用,需要写XXXActivity.this,很多哥们会偷懒,直接就来个getApplicationContext。那么大家有没有想过,XXXActivity.this和getApplicationContext的区别呢?
XXXActivity和getApplicationContext返回的肯定不是一个对象,一个是当前Activity的实例,一个是项目的Application的实例。既然区别这么明显,那么各自的使用场景肯定不同,乱使用可能会带来一些问题。
下面开始介绍在使用Context时,需要注意的问题。

3、引用的保持

大家在编写一些类时,例如工具类,可能会编写成单例的方式,这些工具类大多需要去访问资源,也就说需要Context的参与。
在这样的情况下,就需要注意Context的引用问题。
例如以下的写法:

package com.mooc.shader.roundimageview;  import android.content.Context;  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;  }  //some methods   private void someOtherMethodNeedContext()  {  }  
}  

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

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

这样,我们就解决了内存泄漏的问题,因为我们引用的是一个ApplicationContext,它的生命周期和我们的单例对象一致。
这样的话,可能有人会说,早说嘛,那我们以后都这么用不就行了,很遗憾的说,不行。上面我们已经说过,Context和Application Context的区别是很大的,也就是说,他们的应用场景(你也可以认为是能力)是不同的,并非所有Activity为Context的场景,Application Context都能搞定。
下面就开始介绍各种Context的应用场景。

4、Context的应用场景

这里写图片描述
大家注意看到有一些NO上添加了一些数字,其实这些从能力上来说是YES,但是为什么说是NO呢?下面一个一个解释:
数字1:启动Activity在这些类中是可以的,但是需要创建一个新的task。一般情况不推荐。
数字2:在这些类中去layout inflate是合法的,但是会使用系统默认的主题样式,如果你自定义了某些样式可能不会被使用。
数字3:在receiver为null时允许,在4.2或以上的版本中,用于获取黏性广播的当前值。(可以无视)
注:ContentProvider、BroadcastReceiver之所以在上述表格中,是因为在其内部方法中都有一个context用于使用。

好了,这里我们看下表格,重点看Activity和Application,可以看到,和UI相关的方法基本都不建议或者不可使用Application,并且,前三个操作基本不可能在Application中出现。实际上,只要把握住一点,凡是跟UI相关的,都应该使用Activity做为Context来处理;其他的一些操作,Service,Activity,Application等实例都可以,当然了,注意Context引用的持有,防止内存泄漏。

5、总结

好了,到此,Context的分析基本完成了,希望大家在以后的使用过程中,能够稍微考虑下,这里使用Activity合适吗?会不会造成内存泄漏?这里传入Application work吗?

转载于:https://www.cnblogs.com/codenoodles/p/6421151.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/490368.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

g++编译多个文件

假设现在有一个add.cpp,add.h,main.cpp这三个文件,文件内容如下: add.cpp: add.h: main.cpp: 我需要将add.cpp和main.cpp这两个文件进行编译,有以下两种方法: g -c add.cpp g -c main.cpp g main.o add.o -o test ./test 第二种…

【数字孪生】工业互联网和数字孪生

来源:产业智能官《崛起的超级智能》一书主要阐述当今天人类为人工智能的春天到来而兴奋,为人工智能是否超越人类而恐慌的时候,一个更为庞大、远超人类预期的智能形态正在崛起,种种迹象表明50年来,互联网正在从网状结构…

javascript数组扁平化处理

最近看jQuery源码$.map方法的实现,返回值利用了一个扁平化处理 return ret.concat.apply( [], ret ) 这有个疑问,不知道为什么不直接返回ret 根据这个返回值处理,推测ret可能不是一阶数组,例如[1,2,[3,4]]这样的; var ret [1,2,[…

k折交叉验证法python实现_Jason Brownlee专栏| 如何解决不平衡分类的k折交叉验证-不平衡分类系列教程(十)...

作者:Jason Brownlee编译:Florence Wong – AICUG本文系AICUG翻译原创,如需转载请联系(微信号:834436689)以获得授权在对不可见示例进行预测时,模型评估涉及使用可用的数据集来拟合模型,并评估其表现性能。…

AI“换脸”打开潘多拉魔盒,如何应对?

来源:科学网近日,一款名为“ZAO”的换脸APP引发舆论关注。用户上传照片,就可以把影视剧主角的脸替换成用户自己的脸。在过把“明星瘾”的同时,也让大众关注到“换脸”带来的个人信息泄露风险。信息时代,“脸面”不仅仅…

stm32超声波测距代码_超声波模块另类用法,悬浮,你也能做到

今天,给大家介绍一个「超酷的DIY声波悬浮」研究项目。虽然超声波悬浮,不能像磁悬浮那样悬浮比较重的物品。不过能把小泡沫球、水滴或者蚂蚁这样的小物体悬浮起来也是很有意思的。制作这样一个简易的超声波悬浮器并不需要多少成本,而且材料很容…

【AI战略】2019年美国国家人工智能战略报告(中文翻译版)

来源:AI城市智库人工智能(AI)拥有巨大的希望,几乎可以使社会的各个方面受益,包括经济,医疗保健, 安全,法律,运输,甚至技术本身。2019年2月11日,总统签署了行政命令13859…

函数对象

若一个类重载了运算符“&#xff08;&#xff09;”&#xff0c;则该类的对象就成为函数对象。函数对象可以用于标准库算法。函数对象和函数指针很相似&#xff0c;但也有区别。当函数对象使用模板时可以赋值给函数指针。 #include <iostream #include <vector> #incl…

拍下首张黑洞照片的团队获300万美元奖金:2020年科学突破奖揭晓

来源&#xff1a;科学突破奖科学突破奖2019 年 9 月 5 日&#xff0c;2020 年度突破奖&#xff08;Breakthrough Prize&#xff09;揭晓。突破奖&#xff0c;又被誉为“科学界的奥斯卡”&#xff0c;现已经入第八个年头。突破奖每年都会表彰在生命科学&#xff0c;基础物理学和…

C#获取ip的示例

界面 using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms; namespace TestIP{ public partial class Form1 : Form { public Form1() { InitializeComponent()…

硬盘序列号查询软件_【西数硬盘购买指南】干货——西数移动硬从购买到验证体会心得...

玩摄影有两年多了&#xff0c;所以照片和视频越来越多。上个月618活动&#xff0c;有入手了一块移动硬盘。买多是&#xff1a;西部数据My Passport Ultra移动硬盘4T下面从购买到验证全过程来说图片来源网络图片来源网络一、天猫截图上一篇文章&#xff1a;【希捷硬盘购买指南】…

多角度解析特斯拉电动车技术到底领先了多少?|厚势

来源&#xff1a;Astroys厚势按&#xff1a;不管是豪华车、传统车还是新造车势力造的电动车&#xff0c;都以对标特斯拉为荣。是什么让特斯拉成为电动车的图腾&#xff1f;特斯拉的电动车技术到底领先多少&#xff1f;本文 8000 余字&#xff0c;多个角度进行分析解读。在人们的…

Logistic回归的牛顿法及DFP、BFGS拟牛顿法求解

牛顿法 1 # coding:utf-82 import matplotlib.pyplot as plt3 import numpy as np4 5 def dataN(length):#生成数据6 x np.ones(shape (length,3))7 y np.zeros(length)8 for i in np.arange(0,length/100,0.02):9 x[100*i][0]110 x[100*i][1]…

memcached客户端_分布式算法真是吊炸天 – memcached - 第287篇

相关历史文章&#xff08;阅读本文之前&#xff0c;您可能需要先看下之前的系列 &#xff09;色谈Java序列化&#xff1a;女孩子慎入 - 第280篇烦不烦&#xff0c;别再问我时间复杂度了&#xff1a;这次不色&#xff0c;女孩子进来吧 - 第281篇双向链表&#xff0c;比西天还远&…

2018年中国人工智能100强研究报告

来源&#xff1a;前瞻产业研究院《崛起的超级智能》一书主要阐述当今天人类为人工智能的春天到来而兴奋&#xff0c;为人工智能是否超越人类而恐慌的时候&#xff0c;一个更为庞大、远超人类预期的智能形态正在崛起&#xff0c;种种迹象表明50年来&#xff0c;互联网正在从网状…

印度首次挑战登月告败,一步之遥≈多大差距?

来源&#xff1a;三体引力波&#xff08;the-3body&#xff09;最坏消息还是来了。今天凌晨&#xff0c;印度探测器首次登月尝试&#xff0c;只差一步之遥&#xff0c;距离月表不到2100米&#xff0c;月船2号着陆器与班加罗尔控制中心失去联系&#xff0c;信号中断&#xff0c;…

word交叉引用插入文献后更新域之后编号未更新

这篇文章不教怎么设置交叉引用&#xff0c;这篇文章说的是设好了交叉引用&#xff0c;在某一条文献后面添加了一个文献后&#xff0c;选中全文&#xff0c;右键更新域&#xff0c;编号项仍然没有改变&#xff01;&#xff01; 这是因为刚刚在插入文献时是在上一条文献的编号项…

耐能团队论文登上《自然·电子学》:集成忆阻器与CMOS以实现更好的AI

《自然电子学》杂志封面&#xff08;资料图&#xff0c;来源&#xff1a;《自然》官网&#xff09;来源&#xff1a;Kneron耐能近日&#xff0c;《自然》杂志子刊《自然电子学》&#xff08;Nature Electronics&#xff09;发表论文《集成忆阻器与CMOS以实现更好的AI》&#xf…

word交叉引用多条文献

有时候需要引用多条连续的文献&#xff0c;例如[1][2][3]需要把它变为[1-3]&#xff0c;更新域后不受影响仍然正确。 4、选中这两个代码域&#xff0c;右键->切换域代码&#xff0c;再选中这两个代码域&#xff0c;右键->更新域&#xff0c;引用号码变为[13]&#xff0c;…

pppcloud云主机内LINUX用户安全管理2

◆超级用户权限与授权 ●建立多个超级用户 不少新系统管理员认为root用户是唯一的超级用户&#xff0c;其实root只是系统默认的超级用户的名称&#xff0c;root并非因为它叫root而成为超级用户的。随便打开一个/etc/passwd文件的例子&#xff0c;你就会发现如下几行&#xff1a…