android中this、getAppliaction()、context的区别。
来源:互联网 发布:linux root权限不够 编辑:程序博客网 时间:2024/05/17 23:28
android中this、getAppliaction()、context的区别。
@(android中的小知识)[this|getApplication| context]
在日常的android开发中,我们经常会跟this、getApplication()、context、getApplicationContext()打交道,平时疏于理解,想什么就用什么,今天我们来深入探究,具体来分析分析它们之间的不同。
- this
同Java中的this用法一样,this一般常用的方式就是对当前对象的引用。
当然,我们也可以用this来表示类的成员变量,从而跟我们定义的函数中参数同名的变量用以区分。
this也常用在类的构造方法中来引用满足指定参数类型的构造器。
public class Count { /** * @param args * * */ private String name; private int number; //这是类的成员变量 public Count(String name){ } public Count(String name, int number) { this(name); //->表示调用一个参数的构造器。 this.number =number+6; //this.number->类的成员变量。 number->构造器的参数变量 System.out.println("this.number ="+this.number+"---number="+number); } public static void main(String[] args) { Count count = new Count("aa", 1); // TODO Auto-generated method stub }}
如上图,我们运行程序,在控制台看到的输出结果为:
这里需要注意的是:使用this(name);来表示调用一个参数的构造器时,该代码必须在此构造器方法的第一行,不然会报Constructor call must be the first statement in a constructor
的错误。
类名.this
在android开发中,我们经常会使用如下的形式:
我们在一个类的内部使用this,表示的是对该类的中当前对象的引用。而context
相信大家在日常的android代码编写过程中会经常的用到Contxt。context顾名思义就是上下文、场景的意思,我们用它来获取系统服务、加载资源、 获取内部文件路径等等。
我们找到Context的源码
/** * Interface to global information about an application environment. This is * an abstract class whose implementation is provided by * the Android system. It * allows access to application-specific resources and classes, as well as * up-calls for application-level operations such as launching activities, * broadcasting and receiving intents, etc. */public abstract class Context { /** * File creation mode: the default mode, where the created file can only * be accessed by the calling application (or all applications sharing the * same user ID). * @see #MODE_WORLD_READABLE * @see #MODE_WORLD_WRITEABLE */ public static final int MODE_PRIVATE = 0x0000; public static final int MODE_WORLD_WRITEABLE = 0x0002; public static final int MODE_APPEND = 0x8000; public static final int MODE_MULTI_PROCESS = 0x0004; . . . }
我们从上面源码的注释可以看出Context是一个抽象类,提供了关于应用环境全局信息的接口。它允许获取以应用为特征的资源和类型,是一个统领一些资源(应用程序环境变量等)的上下文。
从上面的类图中我们可以看出,Activity、Application、Service都是其的间接子类。
- Context的使用(getContext()和getApplicationContext())
TextView tv = new TextView(getContext());ListAdapter adapter = new SimpleCursorAdapter(getApplicationContext(), ...);AudioManager am = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);getApplicationContext().getSharedPreferences(name, mode);getApplicationContext().getContentResolver().query(uri, ...);getContext().getResources().getDisplayMetrics().widthPixels * 5 / 8;getContext().startActivity(intent);getContext().startService(intent);getContext().sendBroadcast(intent);
从上面的各种使用方式中我们可以看到Context的使用多种多样,但是它的使用还是要遵循一定的规则,不能想用什么就用什么。不然会造成意想不到的后果,这个我们在后面再说。
在绝大多数的场景下,Activity、Service以及Application这三种类型的Context对象都是可以通用的,不过有几种场景比较特殊,比如启动Activity,还有弹出Dialog。出于安全原因的考虑,Android是不允许Activity或Dialog凭空出现的,一个Activity的启动必须要建立在另一个Activity的基础之上,也就是以此形成的返回栈。而Dialog则必须在一个Activity上面弹出(除非是System Alert类型的Dialog),因此在这种场景下,我们只能使用Activity类型的Context,否则将会出错。
- Context的获取方式和作用域
要想获取Context对象,主要有以下的四种方法:
1.View.getContext,返回当前View的Context对象,通常是当前正在展示的Activity对象。作用域为此Activity内。
2.Activity.getApplicationContext,获取当前Activity所在应用的Context对象。这个Context的作用域为整个应用程序内。
3.ContextWrapper.getBaseContext(),用来获取一个ContextWrapper进行装饰之前的Context,它的作用是在另一个Context中访问context.获得的是一个Activity的Context对象。不怎么常用。这里我们举个例子特别说明下(布局界面很简单,就一个Button这里再不列出xml布局):
package com.example.yyh.test;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.Toast;public class MainActivity extends AppCompatActivity { private Button btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = (Button) findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // Toast.makeText(this,"this的toast",Toast.LENGTH_LONG).show(); //---》错误,不能使用this Toast.makeText(getBaseContext(),"getBaseContext的toast"+getBaseContext(),Toast.LENGTH_LONG).show();//->正确 Toast.makeText(getApplicationContext(),"getApplicationContext的toast"+getApplicationContext(),Toast.LENGTH_LONG).show();//--》正确 } }); }}
第一个Toast报出的错误如下:
因为使用Toast第一个参数必须为一个Context对象,而这里传入的this,实际指的是onClick()方法中的参数View对象,所以报错。(对this不熟悉的可以看看文章开头所讲的this)
我们再看看后面两个Toast中的context,,看看其中的不同。
可以看出,一个是ContextImpl中的Context,返回的是Activity中的Context;一个是Application中的Context。返回的是应用程序的Context。从上面我们分析的Context类图中可以看到,Context抽象类有两个具体的实现类。geBaseContext()是ContextImpl类中的方法,而getApplicationContext()是ContextWrapper的子类Application中的方法。
4.使用this(Activity.this)获得是Acitvity中的context,它的作用域是Activity.
- Context使用隐患
这么多能获得Context对象的方式,我们要慎重选择,因为如果没有考虑清楚,很可能会引起内存泄露的问题。
例如我们自定义的一个MyActivityManager:
public class MyActivityManager{//定义的一个单例activity管理类 private static MyActivityManager sInstance; private Context mContext; public static MyActivityManager getInstance(Context context) { if (sInstance == null) { synchronized(MyActivity.class){ if(sInstance == null){ // 这个类拥有了一个静态的context引用 sInstance = new MyActivityManager(context); } } } return sInstance; } private MyActivityManager(Context context) { mContext = context; }}
然后我们在Activity中应用它:
public class MyActivity extends Activity{ private MyActivityManager manager = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //...layout 初始化 manager = MyActivityManager.getInstance(this); } }
由于MyActivityManager是单例模式,这个类的 生命周期属于整个应用程序,如果这个时候我们关闭了MyActivity,android进行GC操作,但是由于manager仍然引用了MyActivity(在sInstance = new MyActivityManager(context);
),从而导致MyActivity不能被系统回收,造成内存泄露。解决的方式有两种:
1.使用正确的Context
public class MyActivityManager{//定义的一个单例activity管理类 private static MyActivityManager sInstance; private Context mContext; public static MyActivityManager getInstance(Context context) { if (sInstance == null) { synchronized(MyActivity.class){ if(sInstance == null){ // 这个类拥有了一个静态的context引用 /** *这里我们进行一些改变,将context转变为context.getApplicationContext() * */ sInstance = new MyActivityManager(context.getApplicationContext()); } } } return sInstance; } private MyActivityManager(Context context) { mContext = context; }}
还有可以在MyActivity中进行改变:
public class MyActivity extends Activity{ private MyActivityManager manager = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //...layout 初始化 /** *这里我们进行一些改变,将context转变为getApplicationContext() * */ manager = MyActivityManager.getInstance(getApplicationContext()); } }
2.使用弱引用
重新改造单例Activity管理类:
public class MyActivityManager{//定义的一个单例activity管理类 private static MyActivityManager sInstance; private WeakReference<Context> mWRContext; public static MyActivityManager getInstance(Context context) { if (sInstance == null) { synchronized(MyActivity.class){ if(sInstance == null){ // 这个类拥有了一个静态的context引用 sInstance = new MyActivityManager(context); } } } return sInstance; } private MyActivityManager(Context context) { mWRContext = new WeakRefence<Context>(context); }}
总之,使用Context,我们要注意以下几点:
1:当Application的Context能搞定的情况下,并且生命周期长的对象,优先使用Application的Context。
2:不要让生命周期长于Activity的对象持有到Activity的引用。
3:尽量不要在Activity中使用非静态内部类,因为非静态内部类会隐式持有外部类实例的引用,如果使用静态内部类,将外部实例引用作为弱引用持有。
参考
- [Context都没弄明白,还怎么做Android开发?]:http://www.jianshu.com/p/94e0f9ab3f1d
- android中this、getAppliaction()、context的区别。
- Android中Context、getApplication、getApplicationContext、this、Activity.this的区别
- Android 中几个Context的区别,getApplicationContext(),Activity.this,getBaseContext()
- android中this、Activity.this、context区别与联系
- android中获取context的多种方法的区别(this,getbascontext(),getApplicationcontext())
- android中获取context的多种方法的区别(this,getbascontext(),getApplicationcontext())
- getApplicationContext,context,this的区别
- Android学习-this,Context,Activity之间的区别
- Android Context的区别
- this 和 getApplicationContext Context的区别
- this 和 getApplicationContext Context的区别
- this 和 getApplicationContext Context的区别
- this 和 getApplicationContext Context的区别
- this 和context和 getApplictionContext的区别
- Android中this、super的区别
- Android中this、super的区别
- Android中this、super的区别
- Android中this、super的区别
- 没事刷刷算法
- C语言实现词法分析
- Oc UITabBarController+侧滑视图第三方(RESideMenu)demo
- 学习:知识过载与疲于奔命
- SSL2836 2017年11月4日提高组T2 序列(迭代dfs)
- android中this、getAppliaction()、context的区别。
- source insight 配置宏
- do while和while的区别
- Android Studio插件之快速findViewById butterknife和Android CodeGenerator的使用
- 扫描二维码
- 动态规划之字符串分词
- python--leetcode.Detect Capital
- Android使用自定义布局制作进度圆
- 在 CentOS7 上安装 Zookeeper-3.4.9 服务