当前位置: 首页 > news >正文

Android StateFlow初探

Android StateFlow初探

前言:

最近在学习StateFlow,感觉很好用,也很神奇,于是记录了一下.

1.简介:

StateFlow 是一个状态容器式可观察数据流,可以向其收集器发出当前状态更新和新状态更新。还可通过其 value 属性读取当前状态值。如需更新状态并将其发送到数据流,请为 MutableStateFlow 类的 value 属性分配一个新值。

2.和Flow、LiveData联系,官网解释如下:

StateFlow、Flow 和 LiveData

StateFlow 和 LiveData 具有相似之处。两者都是可观察的数据容器类,并且在应用架构中使用时,两者都遵循相似模式。

但请注意,StateFlow 和 LiveData 的行为确实有所不同:

  • StateFlow 需要将初始状态传递给构造函数,而 LiveData 不需要。
  • 当 View 进入 STOPPED 状态时,LiveData.observe() 会自动取消注册使用方,而从 StateFlow 或任何其他数据流收集数据的操作并不会自动停止。如需实现相同的行为,您需要从 Lifecycle.repeatOnLifecycle 块收集数据流。

3.MainViewModel代码:

package com.example.stateflowdemo.viewmodelimport androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.stateflowdemo.model.LoginUIState
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
@ExperimentalCoroutinesApi
class MainViewModel :ViewModel(){private val _loginUIState = MutableStateFlow<LoginUIState>(LoginUIState.Empty)val loginUiState: StateFlow<LoginUIState> = _loginUIStatefun login(username:String,password: String) = viewModelScope.launch {_loginUIState.value = LoginUIState.Loadingdelay(2000L)if(username == "android" && password == "123456") {_loginUIState.value = LoginUIState.Success} else {_loginUIState.value = LoginUIState.Error("账号或密码不正确,请重试")}}
}

4.LoginUIState代码:

sealed class LoginUIState {object Success : LoginUIState()data class Error(val message: String) : LoginUIState()object Loading : LoginUIState()object Empty : LoginUIState()
}

5.测试代码:

package com.example.stateflowdemoimport androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.viewModels
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import com.example.stateflowdemo.databinding.ActivityMainBinding
import com.example.stateflowdemo.model.LoginUIState
import com.example.stateflowdemo.viewmodel.MainViewModel
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.ExperimentalCoroutinesApi
@OptIn(ExperimentalCoroutinesApi::class)
class MainActivity : AppCompatActivity() {private lateinit var binding: ActivityMainBindingprivate val viewModel:MainViewModel by viewModels()override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)initView()initViewModel()}private fun initView() {binding.btnLogin.setOnClickListener {viewModel.login(binding.etUsername.text.toString(),binding.etPassword.text.toString())}}private fun initViewModel() {lifecycleScope.launchWhenStarted {viewModel.loginUiState.collect {listOf(when (it) {is LoginUIState.Success -> {Snackbar.make(binding.root,"Successfully logged in",Snackbar.LENGTH_LONG).show()binding.progressBar.isVisible = false}is LoginUIState.Error -> {Snackbar.make(binding.root,it.message,Snackbar.LENGTH_LONG).show()binding.progressBar.isVisible = false}is LoginUIState.Loading -> {binding.progressBar.isVisible = true}else -> Unit})}}}
}

6.布局代码如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"tools:context=".MainActivity"><com.google.android.material.textfield.TextInputLayoutandroid:id="@+id/textInputLayout"android:layout_width="0dp"android:layout_height="wrap_content"android:hint="Username"android:layout_marginStart="20dp"android:layout_marginEnd="20dp"app:layout_constraintVertical_chainStyle="packed"app:layout_constraintBottom_toTopOf="@+id/textInputLayout2"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_bias="0.5"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"><com.google.android.material.textfield.TextInputEditTextandroid:id="@+id/etUsername"android:layout_width="match_parent"android:layout_height="match_parent"android:ems="15" /></com.google.android.material.textfield.TextInputLayout><com.google.android.material.textfield.TextInputLayoutandroid:id="@+id/textInputLayout2"android:layout_width="0dp"android:layout_height="wrap_content"android:hint="Password"android:layout_marginTop="20dp"android:layout_marginStart="20dp"android:layout_marginEnd="20dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_bias="0.5"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/textInputLayout"><com.google.android.material.textfield.TextInputEditTextandroid:id="@+id/etPassword"android:layout_width="match_parent"android:layout_height="match_parent"android:inputType="textPassword"android:ems="15" /></com.google.android.material.textfield.TextInputLayout><Buttonandroid:id="@+id/btnLogin"android:layout_width="150dp"android:layout_height="wrap_content"android:text="Login"android:layout_marginTop="8dp"app:layout_constraintEnd_toEndOf="@+id/textInputLayout2"app:layout_constraintTop_toBottomOf="@+id/textInputLayout2" /><ProgressBarandroid:id="@+id/progressBar"android:layout_width="wrap_content"android:layout_height="wrap_content"android:visibility="gone"app:layout_constraintBottom_toBottomOf="@+id/btnLogin"app:layout_constraintEnd_toEndOf="@+id/textInputLayout2"app:layout_constraintStart_toStartOf="@+id/textInputLayout2"app:layout_constraintTop_toTopOf="@+id/btnLogin" /></androidx.constraintlayout.widget.ConstraintLayout>

7.实现的效果图如下:

在这里插入图片描述
在这里插入图片描述

8.demo源码地址:

https://gitee.com/jackning_admin/state-flow-sample

http://www.lryc.cn/news/170600.html

相关文章:

  • Docker Compose初使用
  • 测试与FastAPI应用数据之间的差异
  • WebStorm 2023年下载、安装教程、亲测有效
  • k8s储存卷
  • 【解决Win】“ 无法打开某exe提示无法成功完成操作,因为文件包含病毒或潜在的垃圾软件“
  • SpringBoot调用ChatGPT-API实现智能对话
  • element-table出现错位解决方法
  • DC电源模块具有不同的安装方式和安全规范
  • zabbix自定义监控、钉钉、邮箱报警
  • 短信、邮箱验证码本地可以,部署到服务器接口却不能使用
  • Java web基础知识
  • 【Linux学习】01Linux初识与安装
  • android 将数据库中的 BLOB 对象动态加载为 XML,并设置到 Android Activity 的内容视图上
  • Android12之强弱智能指针sp/wp循环引用死锁问题(一百六十六)
  • springboot自定义Json序列化返回,实现自动转换字典值
  • Lostash同步Mysql数据到ElasticSearch(二)logstash脚本配置和常见坑点
  • 兔兔答题企业版1.0.0版本全网发布,同时开源前端页面到unicloud插件市场
  • 76、SpringBoot 整合 MyBatis------使用 sqlSession 作为 Dao 组件(就是ssm那一套,在 xml 写sql)
  • 【ROS】RViz、Gazebo和Navigation的关系
  • 智能井盖:提升城市井盖安全管理效率
  • JavaWeb开发-06-SpringBootWeb-MySQL
  • 十六、垃圾回收相关概念
  • hive、spark、presto 中的增强聚合-grouping sets、rollup、cube
  • elasticsearch bulk 批量操作
  • 力扣11、 盛最多水的容器
  • IIC协议详解
  • element ui-表头自定义提示框
  • Python 图形化界面基础篇:创建顶部菜单
  • java实现十大排序算法
  • Linux日志管理-logrotate(crontab定时任务、Ceph日志转储)