?ViewModel? ? ? ?
? ? ? ? ?这一节了解一下ViewModel,ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。架构组件为界面控制器提供了 ViewModel 辅助程序类,该类负责为界面准备数据。在配置更改期间会自动保留 ViewModel对象,以便它们存储的数据立即可供下一个 activity 或 fragment 实例使用。ViewModel管理的数据为什么不会消失呢,是因为ViewModel的生命周期,如图:
例子:
?ViewModel的另一个特点就是同一个Activity的Fragment之间可以使用ViewModel实现共享数据。来看一个小栗子:
第一步:添加依赖
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
如果不想findviewById,需添加
app下gradle:
plugins {
id 'kotlin-android-extensions'
}
项目下gradle:
classpath "org.jetbrains.kotlin:kotlin-android-extensions:1.3.61"
主要代码:
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class SharedViewModel: ViewModel() {
val inputNumber = MutableLiveData<Int>()
}
class InputFragment : Fragment() {
private var sharedViewModel: SharedViewModel? =null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_input, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
activity?.let {
sharedViewModel = ViewModelProviders.of(it).get(SharedViewModel::class.java)
}
et_input?.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun afterTextChanged(p0: Editable?) {
}
override fun onTextChanged(txt: CharSequence?, p1: Int, p2: Int, p3: Int) {
txt?.let {
var input = 0
if(txt.toString().isNotEmpty()) {
input = txt.toString().toInt()
}
sharedViewModel?.inputNumber?.postValue(input)
}
}
})
}
companion object {
}
}
class OutputFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_output, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
activity?.let {
val sharedViewModel = ViewModelProviders.of(it).get(SharedViewModel::class.java)
observeInput(sharedViewModel)
}
}
@SuppressLint("SetTextI18n")
private fun observeInput(sharedViewModel: SharedViewModel) {
sharedViewModel.inputNumber.observe(viewLifecycleOwner, Observer {
it?.let {
tv_output?.text = "2 x $it = ${2*it}"
}
})
}
companion object {
}
}
class ViewModelActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.viewmodel_main)
supportFragmentManager.beginTransaction().add(R.id.layout_top,InputFragment()).commit()
supportFragmentManager.beginTransaction().add(R.id.layout_bottom,OutputFragment()).commit()
val message = resources.getString(R.string.show_input)
val sharedViewModel = ViewModelProviders.of(this).get(SharedViewModel::class.java)
sharedViewModel.inputNumber.observe(this, Observer {
it?.let {
tv_show_input.text = "$message $it"
}
})
}
}
布局文件: viewmodel_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/layout_top"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:id="@+id/tv_show_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="You input is"
android:textSize="18sp" />
<FrameLayout
android:id="@+id/layout_bottom"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3" />
</LinearLayout>
fragment_input.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#79ce98"
android:orientation="vertical"
android:padding="10dp">
<EditText
android:id="@+id/et_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/input_hint"
android:inputType="numberSigned"
android:maxLength="4"
android:maxLines="1" />
</LinearLayout>
fragment_output.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#81c1d4"
android:gravity="center"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/result"
android:textSize="18dp" />
<TextView
android:id="@+id/tv_output"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp" />
</LinearLayout>
strings.xml
<string name="show_input">Your input is </string>
<string name="input_hint">Enter a number</string>
<string name="result">Result</string>
参考: 官方文档:ViewModel
谷歌实验室
|