我有一个单例,用于打开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)
}
}
答案 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"
...