• Context——Activity与Application之间的桥梁

    Context的使用原理
    服务器君一共花费 12.039 ms 进行了 4 次数据库查询,努力地为您提供了这个页面。
    广告很萌的

    Context就是一个作为接口使用的抽象类,而且这个接口提供的是应用的全局信息,因为是android系统所提供的,所以我们大多时候都是可以直接得到的,这点会在下面讲到。我们来看看它的用处,允许我们获取以应用为特征的资源和类型,同时启动应用级的操作。什么意思?通俗来讲,就是我们可以获取其他应用的资源和类,至于下半句的启动应用级的操作,我们可以暂时忽略,因为不是这里的重点。

    Context的最大作用就是我们可以通过传递它来获得其他Activity或Application的相关资源和方法,它就相当于它们的引用,我们通过引用来获得对象的封装,这也是我们面向对象的基础,所以,我们主要利用它来加载和访问资源。

    Context的类型有两种,一种是Activity-Context,另一种是Application-Activity,这两种的区别就在于它们的生命周期不一样,一个是随着Activity的销毁而销毁,另一个是伴随整个Application,鉴于我们以前学习java,C++这些语言的经验,都会意识到,这些生命周期的不同可能会导致不同行为以及一些错误,这些都会在接下来讲到,因为它们是我们使用Context必须注意的。

    Application-Context

    这个之所以先讲,是因为这个比较麻烦,在于它的获取需要通过一些手段。

    Application-Context的生命周期是整个应用,所以,对于它的使用必须慎重,大部分情况下都要避免使用它,因为它会导致内存泄露的问题。我们先来举个例子,如果我们现在在一个Activity中引入一个Application-Context,那么,当我们这个Activity关闭的时候,这个Application-Context是不会消失的,因为它的生命周期要比我们的Activity长,如果只是一些用来计算的数据还好,但是如果这个Context与我们的Activity的创建有关,或者与我们在Activity要销毁的资源比如图片资源有关,那么,问题就大条了!因为我们的Activity或图片就不能正常销毁,因为它与Application-Context相关联,如果不能正常的释放掉与它们相关的内存,就会出现所谓的内存泄露的问题。这种问题有时候是非常隐晦的,以至于我们根本无法察觉到,所以我们必须遵守相关的使用原则。

    现在我们以一个例子来示例如何获得Application-Context。

    要想获得Application-Context,我们可以先声明一个Application的子类。

    class A extends Application{}
    

    现在,我们在这个类中添加一些东西来证明可以通过Context来获得A的相关资源和方法。这次我们使用一个Toast。

    首先,是在我们的类A里添加以下的内容:

    String s = "hello";
    public String getString(String str){
    	s = str;
    	return s;
    }
    

    然后再在我们的Activity B中尝试取用A的数据和方法:

    A a = (A)getApplicationContext();
    String s = a.s;
    s = a.getString("hello word");
    Toast.makeText(this, s, Toast.LENGTH_LONG).show();
    

    然后我们还必须注意在我们的mainfest文件中注册我们的application:

    <application android:name=".A"></application>
    

    注意,我们的mainfest文件中一开始aplication是没有名字的,因为我们一般都只是启动一个Activity,而不是一个application,所以,可以将我们这个application的名字注册为继承自Application的子类A,这样才能正常显示出一个Toast出来。如果没有这么做,就可能报出这样的错误:android.app.Application cannot be cast to A。

    在上面的例子中可以看到,通过一个Application的子类就能在我们的Activity中调用它的资源和方法,但是其实完全可以不用这样做,声明一个class,然后new一个实例同样可以做到这点,但是这里只是想要大家明白,Context的确可以传递相关类的引用,并且通过这个引用来获取相关类的资源和方法,而且这个Context甚至可以转化为具体的子类,我们的getApplicationContext()返回的其实是一个Context,之所以能将它转换为A,是因为Context传递的就是Application-Context,它是一个Application类型的,而类A是Application的子类,父类转化为子类,这里就会有个疑问,就是我们的父类是不可以强制转化为子类的,因为子类可能有父类没有的方法,这样的转化就会出现问题,但是,我们也知道,可以将子类的引用转化为父类,因为父类的引用是可以指向子类的,所以这里是想说明我们的Context真的是一个引用。

    Application-Context的生命周期为整个Application,所以如果是一些需要在整个应用期间都存在的资源,我们可以将它放进一个Application-Context中,然后通过获取这个Context来使用它们。

    Activity-Context

    正如上面讲的一样,这个Context的生命周期是和得到它的引用的Activity一样长,如果这个Activity结束了,那么,这个Context也会得到释放。它并不像我们上面的Application-Context需要特意去获得,可以在一个Activity中使用this就可以获得当前Activity的Context。还是拿上面例子中的Toast.makeText(this, s, Toast.LENGTH_LONG).show(),其中的this就是当前的Activity-Context,但是,一味的使用this是很危险的,我们要注意的就是,在匿名内部类如果单纯只是使用this是会出错的,因为内部类中使用this得到的是内部类的对象引用,而不是我们要得到的外部类的引用,于是,这时候就必须使用类名.this这种方式,这种做法在按钮的事件监听中是特别要注意的。

    使用规则

    因为使用Application-Cntext会出现内存泄露的危险,所以我们一般都是使用Activity-Context。下面就是这两者的使用规则:

    不要让生命周期长的对象引用Activity-Context,保证引用要与Ativity本身生命周期是一样的,对于生命周期长的对象,使用Application-Context 。

    如果你想要在某个Activity的界面上显示某个组件,比如说Toast,那么,请把你的Activity的Context作为参数传给Toast,这样就能将你的Activity和Toast关联起来,但是,如果你想要在一个Activity中设置好你的Toast,然后再在另一个Activity中显示,记住,你可以有两种选择,一种,就是通过我们的Intent:

    Intent intent = new Intent(Activity1.this, Activity2.class);
    startActivity(intent);
    

    这个Activity1就是我们要显示Toast的Activity,而Acticity2就是我们设置Toast的Activity。

    但是,如果想要在Activity1中调用Toast.show(),接受Activity2中返回的Toast的话,那么,使用默认的样式是非常简单的,如果你真的想要使用自定义的格式,自定义一个布局文件Toast.xml,那么,请在你的Activity1中写下这几句:

    LayoutInflater layout = getLayoutInflater();
    View view = layout.inflate(R.layout.toast, null);  
    

    记住,必须是在setContentView()之后进行切换,不然就会报错,而且,必须是在你要显示的Activity的setContentView(),如果你放在Activity2中的setContentView()也是会出错,就是空指针,因为我们的layout的元素只有在setContentView()之后才开始分配内存,而且我们只是调用Activity2的方法而已,并没有启动Activity2,这点必须注意。

更多 推荐条目

Welcome to NowaMagic Academy!

现代魔法 推荐于 2013-02-27 10:23   

本章最新发布
随机专题
  1. [移动开发] Android根基概念Context 8 个条目
  2. [Python程序设计] Django模板系统 11 个条目
  3. [移动开发] 从代码角度去认识HttpClient 2 个条目
  4. [Python程序设计] Python HTTP服务器 7 个条目
  5. [移动开发] Android 网络通信框架Volley 1 个条目
  6. [软件工程与项目管理] 呈现器的布局与绘制 11 个条目
  7. [移动开发] Layout_weight属性解析 5 个条目
  8. [JavaScript程序设计] Web实时通信技术名词解析 5 个条目
  9. [运维管理] 路由器与交换机 4 个条目
  10. [Python程序设计] Tornado源码解析 23 个条目
  11. [搜索引擎优化] 百度搜索引擎优化指南 3 个条目
  12. [软件工程与项目管理] 浏览器的CSS解析 7 个条目
窗口 -- [协会]