在 ViewModel 环境中哪里轮询传感器数据?

gun*_*bur 1 android viewmodel kotlin sensormanager

我喜欢使用 mvvm 从片段获取传感器数据(例如陀螺仪)。到目前为止,我已经让它工作了,但只是在一个片段中,完全围绕 mvvm 环境工作。它不适用于视图模型文件。如何将传感器数据传输到 LiveData 中?

这是工作代码,但绕过了视图模型:

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) {

}
Run Code Online (Sandbox Code Playgroud)

Paw*_*wel 7

您可以编写自定义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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用此 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
    }
}
Run Code Online (Sandbox Code Playgroud)