在单例内部访问应用程序上下文

时间:2020-08-24 20:16:29

标签: android kotlin

我有一个单例,用于打开JSON资产并将其作为列表返回。我需要访问应用程序上下文才能使用资产管理器。我无法传递上下文,因为我是从视图模型调用的,该模型无法访问应用程序上下文。我已经做了很多搜索,但似乎找不到答案。

import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory

object ProgramListService {
    fun getProgramList(): List<ProgramList>? {

        val moshi = Moshi.Builder()
            .add(KotlinJsonAdapterFactory())
            .build()
        
        val json = context.assets.open("programs/home.json").bufferedReader().use{ it.readText() }
        val listType = Types.newParameterizedType(List::class.java, ProgramList::class.java)
        val adapter: JsonAdapter<List<ProgramList>> = moshi.adapter(listType)

        return adapter.fromJson(json)
    }
}

3 个答案:

答案 0 :(得分:1)

上下文在ViewModel中不好,甚至在应用程序上下文中也不好,AndroidViewModel使用也不好。因此,您可以将AssetManager传递到ViewModel中,然后再将其传递到ProgramListService中,从而避免了上下文的需要,但是Asset Manager在视图模型中仍然有些奇怪。

因此您可以跳过视图模型,并将应用程序上下文直接传递到您的单例ProgramListService中。

object ProgramListService {
    lateinit var application: Application // Add this

    ...
}

然后从活动的onCreate或最适合您的项目的地方,

ProgramListService.application = context.applicationContext as Application

或者像@ Tenfour04一样,建议的应用程序可以安全地创建全局属性

答案 1 :(得分:0)

您在ViewModel中拥有上下文

public class HomeViewModel extends AndroidViewModel {

public HomeViewModel(Application application) {
    super(application);

    Context context = getApplication().getApplicationContext();

}}

答案 2 :(得分:0)

我会毫不犹豫地称呼您有单身人士,因为它没有任何状态。您已经使用object来组织Java中静态方法的名称空间。

如果您的ViewModel是AndroidViewModel,则它带有Application实例,因此您可以将其用作上下文:

class MyViewModel(val application: Application): AndroidViewModel(application) {
    fun foo() {
        someRepoAccessCall(application)
    }
}

由于该应用程序可以安全地用作单例,因此您也可以为其创建一个全局属性,该属性最初是在onCreate()中设置的。

lateinit var application: MyApplication

class MyApplication(): Application
    override fun onCreate() {
        super.onCreate()
        application = this
    }
}

别忘了在清单中分配自定义Application类:

<application
        android:name=".MyApplication"
        ...