当前位置: 首页 > 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

相关文章:

Android StateFlow初探

Android StateFlow初探 前言&#xff1a; 最近在学习StateFlow&#xff0c;感觉很好用&#xff0c;也很神奇&#xff0c;于是记录了一下. 1.简介&#xff1a; StateFlow 是一个状态容器式可观察数据流&#xff0c;可以向其收集器发出当前状态更新和新状态更新。还可通过其 …...

Docker Compose初使用

简介 Docker-Compose项目是Docker官方的开源项目&#xff0c;负责实现对Docker容器集群的快速编排。 Docker-Compose将所管理的容器分为三层&#xff0c;分别是 工程&#xff08;project&#xff09;&#xff0c;服务&#xff08;service&#xff09;以及容器&#xff08;cont…...

测试与FastAPI应用数据之间的差异

【squids.cn】 全网zui低价RDS&#xff0c;免费的迁移工具DBMotion、数据库备份工具DBTwin、SQL开发工具等 当使用两个不同的异步会话来测试FastAPI应用程序与数据库的连接时&#xff0c;可能会出现以下错误&#xff1a; 在测试中&#xff0c;在数据库中创建了一个对象&#x…...

WebStorm 2023年下载、安装教程、亲测有效

文章目录 简介安装步骤常用快捷键 简介 WebStorm 是JetBrains公司旗下一款JavaScript 开发工具。已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源&#xff0c;继承了IntelliJ IDEA强大的JS部分的…...

k8s储存卷

卷的类型 In-Tree存储卷插件 ◼ 临时存储卷 ◆emptyDir ◼ 节点本地存储卷 ◆hostPath, local ◼ 网络存储卷 ◆文件系统&#xff1a;NFS、GlusterFS、CephFS和Cinder ◆块设备&#xff1a;iSCSI、FC、RBD和vSphereVolume ◆存储平台&#xff1a;Quobyte、PortworxVolume、Sto…...

【解决Win】“ 无法打开某exe提示无法成功完成操作,因为文件包含病毒或潜在的垃圾软件“

在下载某个应用程序&#xff0c;打开时出现了“无法成功完成操作因为文件包含病毒或潜在垃圾”的提示&#xff0c;遇到这个情况怎么解决&#xff1f; 下面为大家分享故障原因及具体的处理方法。 故障原因 是由于杀毒 防护等原因引起的。 解决方案 打开Windows 安全中心 选择…...

SpringBoot调用ChatGPT-API实现智能对话

目录 一、说明 二、代码 2.1、对话测试 2.2、单次对话 2.3、连续对话 2.4、AI绘画 一、说明 我们在登录chatgpt官网进行对话是不收费的&#xff0c;但需要魔法。在调用官网的API时&#xff0c;在代码层面上使用&#xff0c;通过API KEY进行对话是收费的&#xff0c;不过刚…...

element-table出现错位解决方法

先看示例图&#xff0c;这个在开发中还是很常遇到的&#xff0c;在table切换不同数据时或者切换页面时&#xff0c;容易出现&#xff1a; 解决方法很简单&#xff0c;官方有提供方法&#xff1a; 我们可以在重新渲染数据后&#xff1a; this.$nextTick(() > {this.$refs.…...

DC电源模块具有不同的安装方式和安全规范

BOSHIDA DC电源模块具有不同的安装方式和安全规范 DC电源模块是将低压直流电转换为需要的输出电压的装置。它们广泛应用于各种领域和行业&#xff0c;如通信、医疗、工业、家用电器等。安装DC电源模块应严格按照相关的安全规范进行&#xff0c;以确保其正常运行和安全使用。 D…...

zabbix自定义监控、钉钉、邮箱报警

目录 一、实验准备 二、安装 三、添加监控对象 四、添加自定义监控项 五、监控mariadb 1、添加模版查看要求 2、安装mariadb、创建用户 3、创建用户文件 4、修改监控模版 5、在上述文件中配置路径 6、重启zabbix-agent验证 六、监控NGINX 1、安装NGINX&#xff0c…...

短信、邮箱验证码本地可以,部署到服务器接口却不能使用

应对公司双验证要求&#xff0c;对本系统做邮箱、短信验证码登录&#xff0c;本地开发正常发送&#xff0c;到服务器上部署却使用失败&#xff0c;已全部解决&#xff0c;记录坑。 一、nginx拦截 先打开你的服务器 nginx.conf 看看有没有做接口拦截。&#xff08;本地可能做Sp…...

Java web基础知识

Servlet Servlet是sun公司开发的动态web技术 sun在API中提供了一个接口叫做 Servlet &#xff0c;一个简单的Servlet 程序只需要完成两个步骤 编写一个实现了Servlet接口的类 把这个Java部署到web服务器中 一般来说把实现了Servlet接口的java程序叫做&#xff0c;Servlet 初步…...

【Linux学习】01Linux初识与安装

Linux&#xff08;B站黑马&#xff09;学习笔记 01Linux初识与安装 文章目录 Linux&#xff08;B站黑马&#xff09;学习笔记前言01Linux初识与安装操作系统简述Linux初识虚拟机介绍安装VMware Workstation虚拟化软件VMware中安装CentOS7 Linux操作系统下载CentOS操作系统VMwa…...

android 将数据库中的 BLOB 对象动态加载为 XML,并设置到 Android Activity 的内容视图上

以下是一个示例代码,演示如何将数据库中的 BLOB 对象动态加载为 XML,并设置到 Android Activity 的内容视图上: ```java import android.app.Activity; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import and…...

Android12之强弱智能指针sp/wp循环引用死锁问题(一百六十六)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:Android…...

springboot自定义Json序列化返回,实现自动转换字典值

自定义序列化 原理 当你使用Spring Boot的Spring Data或者Spring MVC等组件来处理JSON序列化时&#xff0c;Spring框架会在需要将Java对象转换为JSON字符串时调用JsonSerializer。这通常发生在控制器方法返回JSON响应时&#xff0c;或者在将对象保存到数据库等操作中。 // 注册…...

Lostash同步Mysql数据到ElasticSearch(二)logstash脚本配置和常见坑点

1. logstash脚本编写&#xff08;采用单文件对应单表实例&#xff09; 新建脚本文件夹 cd /usr/local/logstash mkdir sql & cd sql vim 表名称.conf #如: znyw_data_gkb_logstash.conf 建立文件夹&#xff0c;保存资源文件更新Id mkdir -p /data/logstash/data/last_r…...

兔兔答题企业版1.0.0版本全网发布,同时开源前端页面到unicloud插件市场

项目说明 兔兔答题是用户端基于uniapp开发支持多端适配&#xff0c;管理端端采用TypeScriptVue3.jselement-plus&#xff0c;后端采用THinkPHP6PHP8Golang开发的一款在线答题应用程序。 问题反馈 线上预览地址 相关问题可以通过下方的二维码&#xff0c;联系到我。了解更多 …...

76、SpringBoot 整合 MyBatis------使用 sqlSession 作为 Dao 组件(就是ssm那一套,在 xml 写sql)

就是 ssm 那套&#xff0c;在xml 上面写sql ★ 基于SqlSession来实现DAO组件的方式 - MyBatis提供的Starter会自动在Spring容器中配置SqlSession&#xff08;其实SqlSessionTemplate实现类&#xff09;、并将它注入其他组件&#xff08;如DAO组件&#xff09;- DAO组件可直接…...

【ROS】RViz、Gazebo和Navigation的关系

1、RViz RViz(Robot Visualization,机器人可视化)是一个用于可视化机器人系统的开源工具,用于显示和调试机器人的传感器数据、状态信息和运动规划等。它是ROS(Robot Operating System)的一部分,是ROS中最常用的可视化工具之一。 RViz:“我们不生产数据只做数据的搬运…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架&#xff0c;该方法利用Stable Diffusion的强大生成能力&#xff0c;仅需单个正常样本和文本描述&#xff0c;即可生成逼真且多样化的异常样本&#xff0c;有效解决了视觉异常检测中异常样本稀缺的难题&#xff0c;为工业质检、医疗影像…...