当前位置: 首页 > 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:“我们不生产数据只做数据的搬运…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...