在 kotlin 的伴随对象中访问应用程序上下文
Access application context in companion object in kotlin
我们如何在 Android kotlin 中访问伴随对象内的应用程序上下文?
我在抽象 class 中有一个伴随对象,我想访问上下文以读取共享首选项,但我无法获取上下文。
更新: 我正在 Android 库中使用这些东西,而且我正在使用的 class 是抽象的
请看这个go to link
class MainApplication : Application() {
init {
instance = this
}
companion object {
private var instance: MainApplication? = null
fun applicationContext() : Context {
return instance!!.applicationContext
}
}
override fun onCreate() {
super.onCreate()
// initialize for any
// Use ApplicationContext.
// example: SharedPreferences etc...
val context: Context = MainApplication.applicationContext()
}
}
像这样扩展应用程序class
import android.app.Application
import android.content.Context
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
MyApplication.appContext = applicationContext
}
companion object {
lateinit var appContext: Context
}
}
然后像这样获取上下文
val context = MyApplication.appContext
实际上我在 Android 库中工作,而 class 是抽象的,所以不能使用已经建议的解决方案。但是,我找到了这样做的方法。
- 在伴生对象中创建一个
lateinit
上下文字段。
abstract class MyClass {
companion object {
private lateinit var context: Context
fun setContext(con: Context) {
context=con
}
}
}
- 然后在应用启动后设置
public class WelcomeActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
MyClass.Companion.setContext(this);
}
}
Firebase 的人写了一篇超酷的文章解释 how their SDK gets hold of the context。
基本上我的内容提供者是这样的:
/**
* This content provider is only responsible to inject the application context into the common module.
*/
class ContextProvider : ContentProvider() {
companion object {
private val TAG = ContextProvider::class.java.simpleName
}
override fun onCreate(): Boolean {
context?.let {
Common.setContext(it)
return true
}
Logger.e(TAG, "Context injection to common failed. Context is null! Check ContextProvider registration in the Manifest!")
return false
}
override fun query(uri: Uri, projection: Array<String>?, selection: String?, selectionArgs: Array<String>?, sortOrder: String?): Cursor? = null
override fun getType(uri: Uri): String? = null
override fun insert(uri: Uri, values: ContentValues?): Uri? = null
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int = 0
override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<String>?): Int = 0
}
而 Common
对象,我将其视为任何 Application
class 的兄弟,如下所示:
/**
* Partially working like an Application class by holding the appContext which makes it accessible inside this module.
*/
@SuppressLint("StaticFieldLeak")
object Common {
/**
* App appContext
*/
@Volatile
lateinit var appContext: Context
var isStoreVersion: Boolean = false
fun setContext(context: Context) {
appContext = context
}
}
如您所见,我还使用标志丰富了 Common
对象,以存储当前版本是否为商店版本。主要是app模块的BuildConfig在某个模块或库中也没有。
不要忘记将 ContentProvider 添加到 <application>
标签内的库的 AndroidManifest
<provider android:name=".util.ContextProvider"
android:authorities="${applicationId}.common.util.contextprovider"
android:exported="false" />
class Test {
companion object {
lateinit var sharedPreferences: SharedPreferences
fun init(context: Context) {
// to prevent multiple initialization
if (!Companion::sharedPreferences.isInitialized) {
sharedPreferences = context.getSharedPreferences("preference_name", Context.MODE_PRIVATE)
}
}
}
}
你可以直接把实例保存在伴生对象里面,在外面访问也没有问题,我觉得这个方法最简单。
重要:将实例属性的可见性更改为private
以确保只有应用程序有写入权限。
class App : Application() {
override fun onCreate() {
super.onCreate()
instance = this
}
companion object {
lateinit var instance: App
private set
}
}
我们如何在 Android kotlin 中访问伴随对象内的应用程序上下文? 我在抽象 class 中有一个伴随对象,我想访问上下文以读取共享首选项,但我无法获取上下文。
更新: 我正在 Android 库中使用这些东西,而且我正在使用的 class 是抽象的
请看这个go to link
class MainApplication : Application() {
init {
instance = this
}
companion object {
private var instance: MainApplication? = null
fun applicationContext() : Context {
return instance!!.applicationContext
}
}
override fun onCreate() {
super.onCreate()
// initialize for any
// Use ApplicationContext.
// example: SharedPreferences etc...
val context: Context = MainApplication.applicationContext()
}
}
像这样扩展应用程序class
import android.app.Application
import android.content.Context
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
MyApplication.appContext = applicationContext
}
companion object {
lateinit var appContext: Context
}
}
然后像这样获取上下文
val context = MyApplication.appContext
实际上我在 Android 库中工作,而 class 是抽象的,所以不能使用已经建议的解决方案。但是,我找到了这样做的方法。
- 在伴生对象中创建一个
lateinit
上下文字段。
abstract class MyClass {
companion object {
private lateinit var context: Context
fun setContext(con: Context) {
context=con
}
}
}
- 然后在应用启动后设置
public class WelcomeActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
MyClass.Companion.setContext(this);
}
}
Firebase 的人写了一篇超酷的文章解释 how their SDK gets hold of the context。
基本上我的内容提供者是这样的:
/**
* This content provider is only responsible to inject the application context into the common module.
*/
class ContextProvider : ContentProvider() {
companion object {
private val TAG = ContextProvider::class.java.simpleName
}
override fun onCreate(): Boolean {
context?.let {
Common.setContext(it)
return true
}
Logger.e(TAG, "Context injection to common failed. Context is null! Check ContextProvider registration in the Manifest!")
return false
}
override fun query(uri: Uri, projection: Array<String>?, selection: String?, selectionArgs: Array<String>?, sortOrder: String?): Cursor? = null
override fun getType(uri: Uri): String? = null
override fun insert(uri: Uri, values: ContentValues?): Uri? = null
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int = 0
override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<String>?): Int = 0
}
而 Common
对象,我将其视为任何 Application
class 的兄弟,如下所示:
/**
* Partially working like an Application class by holding the appContext which makes it accessible inside this module.
*/
@SuppressLint("StaticFieldLeak")
object Common {
/**
* App appContext
*/
@Volatile
lateinit var appContext: Context
var isStoreVersion: Boolean = false
fun setContext(context: Context) {
appContext = context
}
}
如您所见,我还使用标志丰富了 Common
对象,以存储当前版本是否为商店版本。主要是app模块的BuildConfig在某个模块或库中也没有。
不要忘记将 ContentProvider 添加到 <application>
标签内的库的 AndroidManifest
<provider android:name=".util.ContextProvider"
android:authorities="${applicationId}.common.util.contextprovider"
android:exported="false" />
class Test {
companion object {
lateinit var sharedPreferences: SharedPreferences
fun init(context: Context) {
// to prevent multiple initialization
if (!Companion::sharedPreferences.isInitialized) {
sharedPreferences = context.getSharedPreferences("preference_name", Context.MODE_PRIVATE)
}
}
}
}
你可以直接把实例保存在伴生对象里面,在外面访问也没有问题,我觉得这个方法最简单。
重要:将实例属性的可见性更改为private
以确保只有应用程序有写入权限。
class App : Application() {
override fun onCreate() {
super.onCreate()
instance = this
}
companion object {
lateinit var instance: App
private set
}
}