美文网首页
Android 成长笔记1——activity与context

Android 成长笔记1——activity与context

作者: hrisson_71f0 | 来源:发表于2018-11-18 16:38 被阅读0次

    问题环境:重写fragment的onAttach()方法,发现案例中此方法的参数类型为Activity,而实际写出来,系统只承认Context .故借此,学习了解一下二者的区别和联系。

    两者关系如下:


    详情:http://www.cnblogs.com/wenjiang/archive/2012/10/15/2724923.html

    详情如下:

          Context,我们在android开发中经常见到这个名词,尤其是某些方法的参数列表,像是我们Toast中的makeText()中的第一个参数,就是Context。可以这么说,Context是 android中的基础,只有切实掌握好Context的概念和用法,我们才能写出更好的代码。那么,现在就让我们一起来看一下所谓的Context。

          Context,如果是直接从文档翻译过来,就真的是十足的专业了:提供应用环境全局信息的接口,并且这个接口是由抽象类实现的,它的执行被android系统所提供,允许我们获取以应用为特征的资源和类型,同时启动应用级的操作,如启动Activity,broadcasting和接收intent。

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

    一.Context的作用

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

    二 .Context的类型

         Context的类型有两种,一种是Activity-Context,另一种是Application-Activity,这两种的区别就在于它们的生命周期不一样,一个是随着Activity的销毁而销毁,另一个是伴随整个Application。

    1.Application-Context

       生命周期:整个Application

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

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

     1、 不要让生命周期长的对象引用activity context,即保证引用activity的对象要与activity本身生命周期是一样的 ;可以使用application context 

    2、 避免非静态的内部类,尽量使用静态类,避免生命周期问题,注意内部类对外部对象引用导致的生命周期变化

          现在我们以一个例子来示例如何获得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>

         注意,我们的mainfes始的at文件中一开pplication是没有名字的,因为我们一般都只是启动一个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来使用它们。

    2.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这种方式,这种做法在按钮的事件监听中是特别要注意的。

    3.使用规则

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

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

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

    Intent intent =newIntent(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,这点必须注意。

    学习结果:

    1、生命周期是很重要的,如果不想产生不明确的错误,就一定要做在使用前了解该方法的生命周期并正确运用;

    2、个人的问题环境应该不会报错,问题解决

    3、至少看三篇学习笔记,才能做到了解一篇里讲的是什么

    侵删

    相关文章

      网友评论

          本文标题:Android 成长笔记1——activity与context

          本文链接:https://www.haomeiwen.com/subject/ctsgfqtx.html