14.1--全局获取Context 的技巧

回想这么久以来我们所学的内容,你会发现有很多地方都需要用到 Context,弹出 toast 的时侯需要,启动活动的时侯需要,发送广播的时候需要,操作数据库的时侯需要,使用通知的时候需要……。

或许目前你还没有为得不到 Context 而发愁过,因为我们很多的操作都是在活动中进行的,而活动本身就是一个 Context 对象。但是,当应用程序的架构逐渐开始复杂起来的时候,很多的逻辑代码都将脱离 Activity 类,但此时你又恰恰需要使用 Context,也许这个时候你就会感到有些伤脑筋了。

例如,在第12 章的Kotlin 课堂中,我们编写了一个Toast.kt 文件,并在这里对Toast 的用法进行了封装,代码如下所示:

fun String.showToast(context: Context,duration: Int = Toast.LENGTH_SHORT){
    Toast.makeText(context,this,duration).show()
}

fun Int.showToast(context: Context,duration: Int = Toast.LENGTH_SHORT){
    Toast.makeText(context,this,duration).show()
}

可以看到,由于Toast 的makeText() 方法要求传入一个Context 的参数,但是当前代码既不在Activity 中,也不在Service 中,是没有办法直接获取Context 对象的。于是这里我们只好给showToast()  方法添加了一个Context 参数,让调用showToast() 方法的人传递一个Context 对象进来。

虽说这也是一种解决方法,但是有点推卸责任的嫌疑,因为我们将获取Context 的任务转移给了 showToast() 方法的调用方,至于调用方能不能得到Context 参数,那就不是我们需要考虑的问题了。

由此可以看出,在某些情况下,获取Context 并非是那么容易的一件事,有时候还是挺伤脑筋的。不过别担心,下面我们就来学习一种技巧,让你在项目的任何地方都能够轻松获取Context 。

Android 提供了一个Application 类,每当应用程序启动的时候,系统就会自动将这个类进行初始化,而我们可以定制一个自己的Application 类,以便于管理程序内一些全局的状态信息,比如全局Context。

定制一个自己的Application 其实并不复杂,首先需要创建一个MyApplication 类继承自Application ,代码如下所示:

class MyApplication:Application(){
    companion object {
        lateinit var context:Context
    }
    override fun onCreate() {
        super.onCreate()
        context = applicationContext
    }
}

可以看到,MyApplication 中的代码非常简单。这里我们在compantion object 中定义了一个context 变量,然后重写父类的onCreate() 方法,并将调用getApplicationContext() 方法得到的返回值赋值给context 变量,贝尔杨我们就可以以静态变量的形式获取Context 对象了。

需要注意的是,将Context 设置成静态变量很容易会产生内存泄漏的问题,所以这是一种有风险的做法,因此Android Studio 会给出警告提示。

但是由于这里获取的不是Activity 或 Service 中的Context ,而是Application 中的Context,它全局只会存在一份实例,并且在整个应用程序的生命周期内都不会回收,因此是不存在内存泄漏风险的。那么我们可以使用如下注释,让Android Studio 忽略上述警告提示;

class MyApplication:Application(){
    companion object {
        @SuppressLint("StaticFieldLeek")
        lateinit var context:Context
    }
    override fun onCreate() {
        super.onCreate()
        context = applicationContext
    }
}

接下来我们还需要告知系统,当程序启动的时候应该初始化MyApplication 类,而不是默认的Application 类。这一步也很简单,在AndroidManifest.xml 文件的<application>标签下进行制定就可以了,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.jetpacktest">

    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        ...
    </application>

</manifest>

这样我们就实现了一种全局获取Context 的机制,之后不管你想在项目的任何地方使用Context,只需要调用一下MyApplication.context 就可以了。

那么接下来我们再对showToast() 方法进行优化,代码如下所示:

fun String.showToast(duration: Int = Toast.LENGTH_SHORT){
    Toast.makeText(MyApplication.context,this,duration).show()
}

fun Int.showToast(duration: Int = Toast.LENGTH_SHORT){
    Toast.makeText(MyApplication.context,this,duration).show()
}

 可以看到,showToast() 方法不需要再通过传递阐述的方式得到Context 对象,而是调用一下MyApplication.context 就可以了。这样 showToast() 方法的用法也得到了进一步的精简,现在只需要使用如下写法就能弹出一段文字提示:

"This is Toast".showToast() 

 有了这个技巧,你就再也不用为得不到Context 对象而发愁了。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值