android+单利模式中传递context,Android的Context详解
8种机械键盘轴体对比
本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?
Android 是基于Java的,很多时候可以用Java的思想来等同思考,但是却不能和Java进程直接一个Main函数就可以在里面随便new对象来用,像Activity,Service这些必须依靠一个context才可以创建。这是因为Android整体架构是基于组建的应用设计模式,像Activity,Service这些组件的运行需要一个完整的Android工程环境,每个组件就是这个环境中的一个场景,而Context就是这些场景的一些相关信息(也就是上下文环境)。
总结下,Context是维持Android进程中各组件能够正常工作的一个核心功能类。
源码中的注释是这么来解释Context的:Context提供了关于应用环境全局信息的接口。
####Context继承关系图:
Context类本身是一个纯abstract类,它有两个具体的实现子类:ContextImpl和
ContextWrapper。一个包装类而已,ContextWrapper构造函数中必须包含一个真正的Context引用,同时ContextWrapper中提供了attachBaseContext()用于给ContextWrapper对象中指定真正的Context对象,调用ContextWrapper的方法都会被转向其所包含的真正的Context对象。
ContextThemeWrapper类。内部包含了与主题(Theme)相关的接口,这里所说的主题就是指在AndroidManifest.xml中通过android:theme为Application元素或者Activity元素指定的主题。当然,只有Activity才需要主题,Service是不需要主题的,因为Service是没有接口的后台场景,所以Service直接继承于ContextWrapper,Application同理。
ContextImpl类。真正实现了Context中的所有函数,应用进程中所调用的各种Context类的方法,其实现均来自于该类。
总结:Context的两个子类分工明确,其中ContextImpl是Context的具体实现类,ContextWrapper是Context的包装类。Activity,Application,Service虽都继承自ContextWrapper(Activity继承自ContextWrapper的子类ContextThemeWrapper),但它们初始化的过程中都会创建ContextImpl对象,由ContextImpl实现Context中的方法。
Context作用域
如果我们用ApplicationContext去启动一个LaunchMode为standard的Activity的时候会报错android.util.AndroidRuntimeException: Calling startActivity from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?这是因为非Activity类型的Context并没有所谓的任务栈,所以待启动的Activity就找不到栈了。解决这个问题的方法就是为待启动的Activity指定FLAG_ACTIVITY_NEW_TASK标记位,这样启动的时候就为它创建一个新的任务栈,而此时Activity是以singleTask模式启动的。所有这种用Application启动Activity的方式不推荐使用,Service同Application。
在Application和Service中去layout inflate也是合法的,但是会使用系统默认的主题样式,如果你自定义了某些样式可能不会被使用。所以这种方式也不推荐使用。
总结:凡是跟UI相关的,都应该使用Activity做为Context来处理;其他的一些操作,Service,Activity,Application等实例都可以,当然了,注意Context引用的持有,防止内存泄漏。
Context引起的内存泄露
这个是在开发中需要注意的问题,因为不同的context对象所在的场景的生命周期不一样,有些时候某个场景中的context对象已经被GC了,但这个场景还在使用这个context,so,oom出现了。
先写下正确使用Context的note:
使用Context的正确姿势:当Application的Context能搞定的情况下,并且生命周期长的对象,优先使用Application的Context。
不要让生命周期长于Activity的对象持有到Activity的引用。
尽量不要在Activity中使用非静态内部类,因为非静态内部类会隐式持有外部类实例的引用,如果使用静态内部类,将外部实例引用作为弱引用持有。
两个使用Context造成OOM的例子
1. 错误的单例模式1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public class{
private static Singleton instance;
private Context mContext;
private (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掉,这样就导致了内存泄漏。
2. View持有Activity引用1
2
3
4
5
6
7
8
9
10
11
12public class MainActivity extends Activity{
private static Drawable mDrawable;
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掉,所以造成内存泄漏。
android+单利模式中传递context,Android的Context详解相关推荐
- Android Studio工程中添加Admob广告条代码详解
前言: 纵观国内的广告平台,比如多盟,万普,百度,腾讯,或者别的一些广告平台,真是应接不暇,但是具体接入那就自己判断了,经过一番折腾,最终还是选择了谷歌平台,理应是稳定,可靠,安全,收入颇高,但是登录 ...
- android 浏览器 cookie,从Android的浏览器中传递cookie数据到App中
从Android的浏览器中传递cookie数据到App中 蒋彪@南京 2013-4-19 1. 需求 客户有一个需求, 在Android的浏览器上登录一个site, login之后,会在本地co ...
- android中怎么网络判断,Android中判断网络是否连接实例详解
Android中判断网络是否连接实例详解 在android中,如何监测网络的状态呢,这个有的时候也是十分重要的,方法如下: public class ConnectionDetector { priv ...
- android pcm 音量_Android中实时获取音量分贝值详解
基础知识 度量声音强度,大家最熟悉的单位就是分贝(decibel,缩写为dB).这是一个无纲量的相对单位,计算公式如下: 分子是测量值的声压,分母是参考值的声压(20微帕,人类所能听到的最小声压).因 ...
- 阿里聚安全Android应用漏洞扫描器解析:本地拒绝服务检测详解
阿里聚安全Android应用漏洞扫描器解析:本地拒绝服务检测详解 阿里聚安全的Android应用漏洞扫描器有一个检测项是本地拒绝服务漏洞的检测,采用的是静态分析加动态模糊测试的方法来检测,检测结果准确 ...
- Android绘图Canvas十八般武器之Shader详解及实战篇(上)
本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 前言 Android中绘图离不开的就是Canvas了,Canvas是一个庞大的知识体系,有java层的,也有jni层深入到Frame ...
- Android 系统(214)---Android 7.1.1时间更新NITZ和NTP详解
Android 7.1.1时间更新NITZ和NTP详解 1.NTP和NITZ简介 最近在项目中遇到手机首次插上移动卡时不能自动更新时间的问题,就特意跟了下Android系统中手机时间更新有两种方式NT ...
- Android VCard联系人备份恢复(导入/导出)详解
原文地址为: Android VCard联系人备份恢复(导入/导出)详解 首先我们简单的看下在Android中联系人的存储结构. 工作环境:android 2.3.3 联系人的主要数据存放在raw_c ...
- Android基础入门教程——8.3.18 Canvas API详解(Part 3)Matrix和drawBitmapMash
Android基础入门教程--8.3.18 Canvas API详解(Part 3)Matrix和drawBitmapMash 标签(空格分隔): Android基础入门教程 本节引言: 在Canva ...
最新文章
- 企业级Nginx服务基础到架构优化详解--25条
- EqualLogic全攻略视频[(一)介绍]
- Linux中srch出现bash,Shell练习题(3)
- C语言求在算术级数中找到缺少的数字(附完整源码)
- XML file does not appear to have any style information associated with it. XHTML程序出现这个错误
- Servlet使用适配器模式进行增删改查案例(DeptServiceImpl.java)
- ICML2020 | 一行代码就能实现的测试集上分技巧
- C语言extern用法
- Java时间处理方法
- rabbitmq接收不到消息_分布式消息队列:如何保证消息的可靠性传输
- Thinkpad E475换装Win7后,网络连接无故中断无法再次连接的问题
- Excel,WPS如何同时冻结行与列
- Java计算组合数以及生成组合排列
- linux进程监控及管理
- 面试:1.C#中的委托是什么?事件是一种委托吗?
- uilabel 左上对齐_UILabel一行居中对齐与多行左对齐
- Linux操作系统安全(一)
- 存储过程之八-java代码调用oracle存储过程
- mvc中js是如何调用HTML的,MVC中javascript直接调用Model
- Oracle ORA-01017: invalid username/password;解决完一个12560又来一个
热门文章
- Android 的权限级别小记
- 织梦怎么改网站主页php,无忧主机教你修改织梦DedeCms网站首页为动态显示的方法...
- intel 82579v驱动下载_最新INTEL和AMD平台轻松安装WIN7,集成M.2和USB3.0驱动
- ​Microbiome:海南大学张家超、Rob Knight等揭示益生菌在宿主肠道内适应性进化规律...
- Nature综述:植物与微生物组的相互作用:从群落装配到植物健康(上)
- Science:细菌和古菌多重抗性系统抵御噬菌体和外来质粒
- QIIME 2用户文档. 13训练特征分类器Training feature classifiers(2019.7)
- NAR:UNITE真菌鉴定ITS数据库——处理未分类和并行分类(数据库文章阅读模板)
- QIIME 2用户文档. 16鉴定和过滤嵌合体序列q2-vsearch(2018.11)
- R语言置换检验(permutation tests、响应变量是否独立于组、两个数值变量是独立的吗、两个分类变量是独立的吗)、置换检验的基本步骤、R语言自助法Bootstrapping计算置信区间