温馨提示
如果您不知道括号内填写什么类型的参数,按住Ctrl+p
可以提示需要填写参数的类型
访问xml控件的三种方式
- findViewById
- kotlin-android-extensions
- viewBinding视图绑定
ViewBinding
功能:
访问xml中控件
可以通过
binding.视图id
使用相关资源
如何使用:
-
首先需要在gradle中添加如下代码
android { viewBinding { enabled true } }
在MainActivity中使用
lateinit var binding: ActivityMainBinding
来定义一个变量保存binding类对象-
在Oncreate方法中实现如下代码
获取binding类对象
- layoutInflater: Layoutnflater 布局解析器
- 代码中只能使用对应的View或者ViewGroup无法使用xml文件
- 需要使用布局解析器来将xml文件转化为对应的View/ViewGroup
binding = ActivityMainBinding.inflate(layoutInflater)// 将xml的解析 // 将binding类绑定的视图和MainActivity关联 setContentView(binding.root)
数据丢失问题
具体问题
当界面旋转时内容清空了/还原为初始状态了
原因:界面旋转时,activity会被重新加载
解决方案
-
让屏幕支持旋转(横竖屏)(有可能无效,经过本人实现)
此处如果设置将screenOrientation设置为nosensor,由于页面不随手机位置摆放旋转,有效
AndroidManifest.xml中找到对应Activity 设置android:screenOrientation="sensor" unspecified,默认值,由系统决定,不同手机可能不一致 landscape,强制横屏显示 portrait,强制竖屏显 behind,与前一个activity方向相同 sensor,根据物理传感器方向转动,用户90度、180度、270度旋转手机方向,activity都跟随着变化 sensorLandscape,横屏旋转,一般横屏游戏会这样设置 sensorPortrait,竖屏旋转 nosensor,旋转设备时候,界面不会跟着旋转。初始化界面方向由系统控制
-
使用状态保存机制
优点:操作简单 使用onSaveInstanceState存储 ,使用onCreate取出
缺点:- 无法共享
- 进程被销毁时,数据会丢失
Activity提供了状态保存的机制,当界面即将消失时,保存状态值,界面重新显示时读取并显示状态值。使用Bundle来存储数据,通过key-value存取
onSaveInstanceState在界面销毁之前系统自动调用,可以重写此方法,实现自己的目的
//onSaveInstanceState在界面销毁之前系统自动调用,可以重写此方法,实现自己的目的 override fun onSaveInstanceState(outState: Bundle) { // 放入数据 outState.putInt("number",number) // 存储数据 super.onSaveInstanceState(outState) }
取数据
注意:读取数据,系统已经自动写好,使用保存的数据通过
savedInstanceState
的相应方法onCreate时取: override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) //重新读取保存的数据
使用已经保存的数据举例:
savedInstanceState?.getInt("number").also { if (it != null){ number = it binding.textView.text = "$number" } }
ViewModle
ViewModel
类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel
类让数据可在发生屏幕旋转等配置更改后继续留存。
注意:ViewModle也可解决屏幕旋转后的问题
**如何使用?**
定义一个类继承于ViewModel
在类中声明数据和数据相关的逻辑
-
在MainActivity中保存MainViewModel的对象
创建MainViewModel对象
让this(MainActivity)成为这个对象的拥有者,MainViewModel可以感知Activity的生命周期
model = ViewModelProvider(this).get(MainViewModel::class.java)
示例:
class MainActivity : AppCompatActivity() {
//1.定义一个变量保存binding类对象
lateinit var binding:ActivityMainBinding
//定义变量保存viewModel
lateinit var model: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
/**
\* 2.获取binding类对象
\* layoutInflater: LayoutInflater 布局解析器
\* 代码中只能使用对应的View或者ViewGroup无法使用xml文件
\* 需要使用布局解析器来将xml文件转化为对应的View/ViewGroup
*/
binding = ActivityMainBinding.inflate(layoutInflater)
//3.将binding类绑定的视图和MainActivity关联
setContentView(binding.root)
//创建MainViewModel对象
model = ViewModelProvider(this).get(MainViewModel::class.java)
binding.textView.text = "${model.number}"
//4.正常使用
binding.button.setOnClickListener {
/* number++
binding.textView.text = "$number"*/
model.addOne()
binding.textView.text = "${model.number}"
}
//重新读取保存的数据
/*savedInstanceState?.getInt("number").also {
if (it != null){
*//*number = it
binding.textView.text = "$number"*//*
}
}*/
//点击按钮实现跳转
binding.nextBtn.setOnClickListener {
startActivity(Intent(this,SecondActivity::class.java))
}
}
/*//在界面销毁之前调用
override fun onSaveInstanceState(outState: Bundle) {
//存储数据
outState.putInt("number",number)
super.onSaveInstanceState(outState)
}*/
}
如何监听数据?
时刻监听数据也可解决屏幕旋转导致数据显示的问题
1.使用LiveData/MutableData
注意:MutableData为LiveData的子类
- liveData使用步骤
- a.在ViewModel中声明需要监听的对象
var number = MutableLiveData<>() - b.在ViewModel中实现数据改变逻辑
fun addOne(){
number.postValue(number.value!!+1)
} - c.界面中获取ViewModel对象
val model: MainViewModel by viewModels() - d.观察数据并实现改变之后需要处理的业务逻辑
model.number.observe(this){
binding.textView.text = "$it"
}
2.DataBinding
注意:
-
启动DataBinding功能
android{ dataBinding{ enabled true } }
在xml文件的根容器上使用 alt+enter -> convert to data binding layout
<data>
<variable
name="自己定义的变量名" // 例如: viewModel
type="类型的完整路径" // 例如: com.example.lineData.MainViewModel
\>
</data>
-
在xml中给按钮绑定事件:注意->两边的空格
android:onClick="@{() -> viewModel.addOne()}"
-
在xml中绑定数据
android:text="@{String.valueOf(viewModel.number)}"
-
将Activity中创建的ViewModel对象设置给DataBinding中申明的变量
binding.viewModel = model binding.lifecycleOwner = this
-
如果事件需要参数,或者说需要做额外的操作,必须自定义绑定的事件
-
在build.gradle的plugins中导入插件
id 'kotlin-kapt'
-
-
在一个文件中定义好需要绑定的方法(给对应的控件添加扩展)
需要使用@BindingAdapter()注解修饰