我喜欢使用 mvvm 从片段中获取传感器数据(例如陀螺仪(。到目前为止,我让它工作,但只是一个片段,完全围绕 mvvm 环境工作。它不适用于视图模型文件。如何将传感器数据流式传输到实时数据中?
这是工作代码,但绕过视图模型:
class RPMFragment : Fragment(), SensorEventListener {
private lateinit var rpmViewModel: RPMViewModel
private lateinit var sensorManager: SensorManager
private lateinit var gyroscope: Sensor
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
rpmViewModel = ViewModelProviders.of(this).get(RPMViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_rpm, container, false)
val textView: TextView = text_rpm
rpmViewModel.text.observe(this, Observer {
textView.text = it
})
this.sensorManager = activity!!.getSystemService(Context.SENSOR_SERVICE) as SensorManager
sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)?.let {
this.gyroscope = it
}
return root
}
override fun onSensorChanged(event: SensorEvent?) {
if (event?.sensor?.type == Sensor.TYPE_GYROSCOPE) {
text_rpm.text = "z axis: " + event.values[2].toString()
}
}
override fun onResume() {
super.onResume();
sensorManager.registerListener(this, this.gyroscope, SensorManager.SENSOR_DELAY_NORMAL);
// repeat that line for each sensor you want to monitor
}
override fun onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
}
您可以编写自定义LiveData
类来完成"繁重的工作",让您的 ViewModel 只是一个简单的主机:
// viewmodel only serves as a host for livedata
class RPMViewModel(application: Application) : AndroidViewModel(application) {
val rpmLiveData = RPMLiveData()
// inner class just to have access to application
inner class RPMLiveData : LiveData<String>(), SensorEventListener {
private val sensorManager
get() = getApplication<Application>().getSystemService(Context.SENSOR_SERVICE) as SensorManager
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
//unused
}
override fun onSensorChanged(event: SensorEvent) {
postValue("z axis: ${event.values[2]}")
}
override fun onActive() {
sensorManager.let { sm ->
sm.getDefaultSensor(Sensor.TYPE_GYROSCOPE).let {
sm.registerListener(this, it, SensorManager.SENSOR_DELAY_NORMAL)
}
}
}
override fun onInactive() {
sensorManager.unregisterListener(this)
}
}
}
使用此 ViewModel,您的片段现在是轻量级的,并且仅对来自LiveData
的更改做出反应:
class RPMFragment : Fragment() {
private val rpmViewModel by lazy {
ViewModelProviders.of(this).get(RPMViewModel::class.java)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val root = inflater.inflate(R.layout.fragment_rpm, container, false)
rpmViewModel.rpmLiveData.observe(viewLifecycleOwner, Observer {
text_rpm.text = it
})
return root
}
}
您必须使ViewModel扩展AndroidViewModel才能访问当前上下文。然后,让您的 ViewModel 实现 SensorEventListener 接口,以获取有关传感器事件的通知。将事件数据发布到您的实时数据:
class RpmViewModel(application: Application) : AndroidViewModel(application), SensorEventListener {
private lateinit var sensorManager: SensorManager
private lateinit var gyroscope: Sensor
val sensorDataLiveData = MutableLiveData<String>()
fun registerSensors() {
sensorManager = getApplication<Hero2Application>().getSystemService(Context.SENSOR_SERVICE) as SensorManager
sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)?.let {
this.gyroscope = it
}
sensorManager.registerListener(this, this.gyroscope, SensorManager.SENSOR_DELAY_NORMAL);
}
fun unregisterSensors() {
sensorManager.unregisterListener(this)
}
override fun onSensorChanged(event: SensorEvent?) {
if (event?.sensor?.type == Sensor.TYPE_GYROSCOPE) {
sensorDataLiveData.postValue("z axis: " + event.values[2].toString())
}
}
override fun onAccuracyChanged(p0: Sensor?, p1: Int) {
}
}
然后,您可以在片段中收听事件,如下所示:
viewModel.sensorDataLiveData.observe(this, Observer {
Log.d("RPMFragment", it)
})
像以前一样注册和注销:
override fun onResume() {
super.onResume()
viewModel.registerSensors()
}
override fun onPause() {
super.onPause()
viewModel.unregisterSensors()
}