Android Context的几点看法

来源:互联网 发布:靳东人设崩 知乎 编辑:程序博客网 时间:2024/04/25 18:27

一.首先什么是context?

  文档语焉不详,说是resource什么的,反正是没看懂,实际上可以认为它是一个指向parent对象的指针,受到那个parent对象的控制。

二.为什么需要context?

  试想一下这个语句:

  Button myButton =newButton(this);

  这个this就是context,前面说了它指向了parent对象,那指向了哪里?为什么需要这么做?原因是Button为了能完成自己的使命(响应各种操作)就得让Android系统知道自己是属于哪个Activity的,这个信息是必须的,因为只有这样Android系统才会对其进行管理,比如响应onClick()事件,否则系统连Button是属于哪个Activity的都不知道,怎么响应呢?如果Button的context和Activity的context是一样的,那么它们都是可见的,比如上面那个button跟Activity一样是可见的,它们的context指向另一个不可见的对象,也就是它们受那个不可见的对象控制,我理解为系统。

三.Application context和Activity context

  这是两种不同的context,也是最常见的两种。第一种中context的生命周期与Application的生命周期相关的,context随着Application的销毁而销毁,第二种中的context跟Activity的生命周期是相关的,但是对一个Application来说,Activity可以销毁几次,那么属于Activity的context就会销毁多次。至于用哪种context,得看应用场景,个人感觉用Activity的context好一点,不过也有的时候必须使用Application的context。

  举例来说:SQLite建立时是需要context的,那么我们怎么传呢?

1.建立SQLiteOpenHelper 的子类

public class mySQLiteHelper extends SQLiteOpenHelper {..........public DBOpenHelper(Context context, String name, CursorFactory factory,int version) {super(context, name, factory, version);// TODO Auto-generated constructor stub}.......}

2.我们用另一个类封装一下这个类,完善数据查询、插入、删除、更新等操作,具体方法不表

public class DBManager {//定义上面那个类对象;private mySQLiteHelper dbHelper;//注意这里得定义一个context,你想直接得到是得不到的,需要调用这个类的对象自己传一个context过来,这个context再将得到的context传到mySQLiteHelper 那个类去。private Context context;//构造方法public DBManager (Context context) {this.context = context;dbHelper = new DBOpenHelper(context,DB_NAME,null,VERSION);db = dbHelper.getWritableDatabase();}}

3.最后,我们在一个Activity中进行调用

public class myActivity extends Activity {private DBManager db; public void onCreate(Bundle savedInstanceState) {........     //dbmgr = new DataManager(getApplicationContext()); 第一种       dbmgr = new DataManager(this);  //第二种//两种方法都可以,第一种是Application的context,第二种是Activity的context.........}}

  在android中context可以作很多操作,但是最主要的功能是加载和访问资源。在android中有两种context,一种是 application context,一种是activity context,通常我们在各种类和方法间传递的是activity context。
比如一个activity的onCreate:

protected void onCreate(Bundle state) {        super.onCreate(state);        TextView label = new TextView(this); //传递context给view control        label.setText("Leaks are bad");        setContentView(label);}

  把activity context传递给view,意味着view拥有一个指向activity的引用,进而引用activity占有的资源:view hierachy, resource等。这样如果context发生内存泄露的话,就会泄露很多内存。这里泄露的意思是gc没有办法回收activity的内存。Leaking an entire activity是很容易的一件事。

  当屏幕旋转的时候,系统会销毁当前的activity,保存状态信息,再创建一个新的。

  比如我们写了一个应用程序,它需要加载一个很大的图片,我们不希望每次旋转屏 幕的时候都销毁这个图片,重新加载。实现这个要求的简单想法就是定义一个静态的Drawable,这样Activity 类创建销毁它始终保存在内存中。
实现类似:

public class myactivity extends Activity {        private static Drawable sBackground;        protected void onCreate(Bundle state) {                super.onCreate(state);                TextView label = new TextView(this);                label.setText("Leaks are bad");                if (sBackground == null) {                        sBackground = getDrawable(R.drawable.large_bitmap);                }        label.setBackgroundDrawable(sBackground);//drawable attached to a view        setContentView(label);        }}

  这段程序看起来很简单,但是却问题很大。当屏幕旋转的时候会有leak(即gc没法销毁activity)。

  我们刚才说过,屏幕旋转的时候系统会销毁当前的activity。但是当drawable和view关联后,drawable保存了view的 reference,即sBackground保存了label的引用,而label保存了activity的引用。既然drawable不能销毁,它所 引用和间接引用的都不能销毁,这样系统就没有办法销毁当前的activity,于是造成了内存泄露。gc对这种类型的内存泄露是无能为力的。

  避免这种内存泄露的方法是避免activity中的任何对象的生命周期长过activity,避免由于对象对 activity的引用导致activity不能正常被销毁。我们可以使用application context。application context伴随application的一生,与activity的生命周期无关。application context可以通过Context.getApplicationContext或者Activity.getApplication方法获取。

  避免context相关的内存泄露,记住以下几点:

  1. 不要让生命周期长的对象引用activity context,即保证引用activity的对象要与activity本身生命周期是一样的
  2. 对于生命周期长的对象,可以使用application context
  3. 避免非静态的内部类,尽量使用静态类,避免生命周期问题,注意内部类对外部对象引用导致的生命周期变化

  Context字面意思是上下文,位于framework package的android.content.Context中,其实该类为LONG型,类似Win32中的Handle句柄。很多方法需要通过 Context才能识别调用者的实例:比如说Toast的第一个参数就是Context,一般在Activity中我们直接用this代替,代表调用者的实例为Activity,而到了一个button的onClick(View view)等方法时,我们用this时就会报错,所以我们可能使用ActivityName.this来解决,主要原因是因为实现Context的类主要有Android特有的几个模型,Activity以及Service。

  如下图所示:

这里写图片描述

  Context提供了关于应用环境全局信息的接口。它是一个抽象类,它的执行被Android系统所提供。它允许获取以应用为特征的资源和类型。同时启动应用级的操作,如启动Activity,broadcasting和接收intents。

四、HANDLE handle句柄是什么意思,他是指针么?

  一个句柄是指使用的一个唯一的整数值,是指一个四字节长的数值,用于标志应用程序中的不同对象和同类对象中的不同的实例,诸如,一个窗口,按钮,图标,滚动条,输出设备,控件或者文件等,应用程序能够通过句柄访问相应的对象的信息。但是,句柄不是一个指针,程序不能利用它句柄来直接阅读文件中的信息。

感恩:

Android中Context简介:http://blog.csdn.net/zhangqijie001/article/details/5891682

Android Context的几点看法:http://blog.sina.com.cn/s/blog_80bfa06701014c9g.html

Android中,Context,什么是Context?:http://blog.csdn.net/race604/article/details/9331807

android中的Context到底该怎么用 :http://www.cnblogs.com/thinksasa/archive/2012/12/01/2796964.html

0 0