Android基础概念Context的作用

Context而是一个类——如果不太了解面向对象,可以把“类”看做一种数据类型,就像int,不过类型为“类”的数据(称为对象)可能储存远比int多的信息,比如这里的类型为Context的对象就储存关于程序、窗口的一些资源。

有些函数调用时需要一个Context参数,比如Toast.makeText,因为函数需要知道是在哪个界面中显示的Toast。
再比如,Button myButton = new Button(this); 这里也需要Context参数(this),表示这个按钮是在“this”这个屏幕中显示的。
Android开发使用(纯粹的)面向对象语言,一切都是对象,就连我们写的函数都是对象的函数。
public class MainActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toast.makeText(this,
                "OK!", 
                Toast.LENGTH_LONG).show();
        Button button1 = (Button)findViewById(R.id.button1);
        button1.setOnClickListener(new Button.OnClickListener(){ 
            public void onClick(View v)
            {
                Toast.makeText(MainActivity.this,
                        "Hello, world!", 
                        Toast.LENGTH_LONG).show();
            }
        });
    }
}
这里OnCreate就是MainActivity的对象的函数(MainActivity是类),所以这个函数中的this就表示当前的、包含这个函数的MainActivity对象。
MainActivity extends Activity,意思是MainActivity 继承 Activity,即MainActivity 是 Activity 的一种,所有的MainActivity 都是 Activity。同样,在Android文档中Activity继承ContextThemeWrapper,ContextThemeWrapper继承ContextWrapper,ContextWrapper继承Context。所以this这个MainActivity也是Context,把this传入Toast.makeText表示“OK!”是在当前的MainActivity对象(也是Context)中显示的。
对于显示"Hello, world!"的Toast.makeText,这个函数在onClick中,而onClick是new Button.OnClickListener(){...}这个没有名字的类的函数,this表示匿名类的对象,不表示MainActivity对象,所以这里用MainActivity.this,强制选择外面一层MainActivity的this。
PS:定向求助?我不记得我以前回答过Android方面的问题……难道是系统自动发的?



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以及BroadcastReceiver。

  常规需要Context实例的方法主要有各种Service实现的类,比如说SensorManager在实例化时需要getSystemService(String)方法
就必须由Context的实例执行,还有一些私有的文件系统I/O比如说openFileInput以及常用的Toast的makeText方法。

在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 

  privatestatic Drawable sBackground; 

  protectedvoid 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 context3. 避免非静态的内部类,尽量使用静态类,避

免生命周期问题,注意内部类对外部对象引用导致的生命周期变化 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值