根据https://developer.android.com/topic/libraries/architecture/viewmodel中“在片段之间共享数据”部分,我们被告知在活动范围内创建ViewModel并在片段之间共享是一个可行的方法。
这是在ViewModel中设置值的片段
class MasterFragment : Fragment() {
private lateinit var itemSelector: Selector
private lateinit var model: SharedViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
model = activity?.run {
ViewModelProviders.of(this).get(SharedViewModel::class.java)
} ?: throw Exception("Invalid Activity")
itemSelector.setOnClickListener { item ->
// Update the UI
}
}
}
这是使用属性集的详细片段
class DetailFragment : Fragment() {
private lateinit var model: SharedViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
model = activity?.run {
ViewModelProviders.of(this).get(SharedViewModel::class.java)
} ?: throw Exception("Invalid Activity")
model.selected.observe(this, Observer<Item> { item ->
// Update the UI
})
}
}
这是ViewModel
class SharedViewModel : ViewModel() {
val selected = MutableLiveData<Item>()
fun select(item: Item) {
selected.value = item
}
}
我的问题很简单。假设MasterFragment在单击按钮时在ViewModel中设置了一个值,那么当系统杀死我们的应用程序并重新启动它之后,当我们访问该值时,我们将如何恢复该值。
由于我们在MasterFragment上单击按钮进行设置,因此我们的DetailFragment将看不到该值。为了更好地理解该问题,请考虑我们有Fragment A,B,C和D,它们共享一个ViewModel,该ViewModel的值是Fragment A B和C一起计算出的值,并将其放在ViewModel中,以便Fragment D访问。
现在,当系统终止并重新创建应用程序Fragment D时,该值将不再可用。
如果不依靠肮脏的代码,OnSaveInstance也将无济于事。对于简单的情况,是的,但就像FragmentA B和C一起产生值的情况一样,在这种情况下,OnSaveInstance会出现问题。
OnSaveInstance应该位于ViewModel内部,但是我不认为是这种情况。有什么想法吗?
答案 0 :(得分:1)
如果在重置或取消应用程序后仍希望获得存储的价值,则需要将数据保存到SharedPreferences或内部SqLite数据库中,并在应用程序启动后将其还原。
答案 1 :(得分:1)
ViewModel对象的范围是获取ViewModel时传递给ViewModelProvider的生命周期。 ViewModel会一直保留在内存中,直到其生命周期范围永久消失:在活动中,活动结束时;在片段中,活动断开时。
我的问题很简单。假设MasterFragment在buttonClick的ViewModel中设置了一个值,那么当系统杀死我们的应用程序并重新启动它之后,在访问它时我们将如何恢复该值?
如果应用程序被用户或系统杀死或重新启动,则无法恢复该值。
要解决从活动A,活动B和活动C收集数据并将其显示在活动D中的目的,即使应用程序被终止或重新启动,您也可以从以下任意一种方法中进行选择:
1. SharedPreference
2.本地数据库Room或SQLite
3.将数据存储在文件中
我建议您对小数据使用SharedPreference,对大型和复杂数据使用Room。
简而言之,ViewModel临时存储数据以适应方向变化(无需编写onSaveInstanceState
和onRestoreInstanceState
的代码),并在Activity和Fragments之间共享数据。如果活动被破坏或片段被分离,数据将丢失。
答案 2 :(得分:0)
对于那些在那里使用Kotlin的人,请尝试以下方法:
将androidx ViewModel and LiveData库添加到gradle文件中
像这样在片段中调用视图模型:
class MainFragment : Fragment() {
private lateinit var viewModel: ViewModel
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
// kotlin does not have a getActivity() built in method instead we use activity, which is null-safe
activity?.let {
viemModel = ViewModelProvider(it).get(SharedViewModel::class.java)
}
}
}