Android中简单封装Livedata工具类

news2024/11/23 17:00:49

Android中简单封装Livedata工具类

前言:

之前讲解过livedata和viewmodel的简单使用,也封装过room工具类,本文是对livedata的简单封装和使用,先是封装了一个简单的工具类,然后实现了一个倒计时工具类的封装.

1.LiveDataHelper工具类:

package com.example.livedatautilsdemo.helper;


import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;

import java.util.Map;
import java.util.WeakHashMap;

/**
 * @author: njb
 * @date: 2023/7/31 0:10
 * @desc:
 */
public class LiveDataHelper<T>extends MutableLiveData {
    private final WeakHashMap<Observer<T>, Boolean> mObservers = new WeakHashMap<>();

    @Override
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
        mObservers.put((Observer<T>) observer, true);
        super.observe(owner, observer);
    }

    @Override
    public void removeObserver(@NonNull Observer observer) {
        mObservers.remove(observer);
        super.removeObserver(observer);
    }

    @Override
    public void removeObservers(@NonNull LifecycleOwner owner) {
        mObservers.clear();
        super.removeObservers(owner);
    }

    public void setValue(Object value) {
        for (Map.Entry<Observer<T>, Boolean> entry : mObservers.entrySet()) {
            if (entry.getValue()) {
                entry.setValue(false);
                entry.getKey().onChanged((T) value);
            }
        }
    }

    public void call() {
        setValue(null);
    }
}

2.简单使用:

private LiveDataHelper<String> mLiveDataHelper = new LiveDataHelper<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
        initTime();
    }
    
      private void initView() {
        tvName = findViewById(R.id.textview);
        tvTime = findViewById(R.id.tvTime);
    }
        private void initData() {
        mLiveDataHelper.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String name) {
                Log.d("LiveDataDemo", "onChanged: " + name);
            }
        });

        tvName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String newName = "NewName" + new Random().nextInt(100);
                mLiveDataHelper.setValue(newName);
                Log.d("LiveDataDemo", "onClick: " + newName);
                tvName.setText(String.format("名称发生变化:%s", newName));
            }
        });
    }

3.布局代码:

<?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">

    <TextView
        android:id="@+id/textview"
        android:layout_width="200dp"
        android:layout_height="60dp"
        android:text="Hello World!"
        android:background="@color/design_default_color_primary"
        android:textSize="20sp"
        android:textColor="@color/white"
        android:focusable="true"
        android:gravity="center"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/tvTime"
        android:layout_width="200dp"
        android:layout_height="60dp"
        android:background="@color/design_default_color_primary"
        android:text="timer"
        android:textSize="20sp"
        android:textColor="@color/white"
        android:focusable="true"
        android:gravity="center"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/textview"
        android:layout_marginTop="20dp"/>

</androidx.constraintlayout.widget.ConstraintLayout>

4.实现效果如下:

在这里插入图片描述

5.封装一个倒计时工具类:

package com.example.livedatautilsdemo.helper;

import android.os.CountDownTimer;

import androidx.lifecycle.MutableLiveData;

/**
 * @author: njb
 * @date: 2023/8/6 23:37
 * @desc:
 */
public class LiveDataTimeHelper extends MutableLiveData<Long> {
    private CountDownTimer countDownTimer;

    public void startCountDown(long millisInFuture, long countDownInterval) {
        countDownTimer = new CountDownTimer(millisInFuture, countDownInterval) {
            @Override
            public void onTick(long millisUntilFinished) {
                setValue(millisUntilFinished / 1000);
            }

            @Override
            public void onFinish() {
                setValue(0L);
            }
        };
        countDownTimer.start();
    }

    public void stopCountDown() {
        if (countDownTimer != null) {
            countDownTimer.cancel();
        }
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        stopCountDown();
    }
}

6.倒计时Viewmodel:

package com.example.livedatautilsdemo.viewmodel;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.ViewModel;

import com.example.livedatautilsdemo.helper.LiveDataHelper;
import com.example.livedatautilsdemo.helper.LiveDataTimeHelper;

import java.util.Timer;
import java.util.TimerTask;

/**
 * @author: njb
 * @date: 2023/8/2 23:40
 * @desc:
 */
public class TimerLiveDataViewModel extends ViewModel {
    private LiveDataTimeHelper liveDataHelper;

    public LiveDataTimeHelper getCurrentSecondLiveData() {
        if (liveDataHelper == null) {
            liveDataHelper = new LiveDataTimeHelper();
        }
        return liveDataHelper;
    }

    public void startTiming(int seconds) {
        if (liveDataHelper != null) {
            liveDataHelper.startCountDown(seconds * 1000, 1000);
        }
    }

    public void stopTiming() {
        if (liveDataHelper != null) {
            liveDataHelper.stopCountDown();
        }
    }

    @Override
    protected void onCleared() {
        super.onCleared();
        stopTiming();
    }
}

7.简单使用:

package com.example.livedatautilsdemo.viewmodel;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.ViewModel;

import com.example.livedatautilsdemo.helper.LiveDataHelper;
import com.example.livedatautilsdemo.helper.LiveDataTimeHelper;

import java.util.Timer;
import java.util.TimerTask;

/**
 * @author: njb
 * @date: 2023/8/2 23:40
 * @desc:
 */
public class TimerLiveDataViewModel extends ViewModel {
    private LiveDataTimeHelper liveDataHelper;

    public LiveDataTimeHelper getCurrentSecondLiveData() {
        if (liveDataHelper == null) {
            liveDataHelper = new LiveDataTimeHelper();
        }
        return liveDataHelper;
    }

    public void startTiming(int seconds) {
        if (liveDataHelper != null) {
            liveDataHelper.startCountDown(seconds * 1000, 1000);
        }
    }

    public void stopTiming() {
        if (liveDataHelper != null) {
            liveDataHelper.stopCountDown();
        }
    }

    @Override
    protected void onCleared() {
        super.onCleared();
        stopTiming();
    }
}

8.实现效果如下:

在这里插入图片描述

9.项目源码如下:

https://gitee.com/jackning_admin/live-data-utils-demo

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/847085.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

让你的商城触达全球市场!了解跨境商城系统源码的优势

全球市场触达的商机 随着全球化趋势的不断发展&#xff0c;跨境电商已经成为企业开拓全球市场的重要途径之一。在扩大国际业务的同时&#xff0c;企业需要面对许多挑战&#xff0c;如语言、支付、物流等问题。这些问题可以通过使用跨境商城系统源码来解决。 一、多语言支持 跨境…

如何做好电信布线?

电信布线作为通信网络骨干&#xff0c;对于任何现代企业或组织来说都是至关重要的组成部分。随着业务量的持续增长&#xff0c;对电信布线安装提出了更高的要求。为此&#xff0c;飞速&#xff08;FS&#xff09;提出了FHD电信布线解决方案&#xff0c;在满足了电信机房要求的基…

源码分析——ConcurrentHashMap源码+底层数据结构分析

文章目录 1. ConcurrentHashMap 1.71. 存储结构2. 初始化3. put4. 扩容 rehash5. get 2. ConcurrentHashMap 1.81. 存储结构2. 初始化 initTable3. put4. get 3. 总结 1. ConcurrentHashMap 1.7 1. 存储结构 Java 7 中 ConcurrentHashMap 的存储结构如上图&#xff0c;Concurr…

【Vue3】localStorage读取数组并赋值的问题

问题描述 今天在写项目用到localStorage进行存储并读取数据&#xff0c;并将读取到的数据存放到列表的时候&#xff0c;发现vue3不能直接对数组进行赋值。因为Vue3的响应式是proxy&#xff0c;对所有的数据进行了拦截。 onBeforeMount(() > {console.log(JSON.parse(local…

C语言学习笔记 使用vscode外部console出现闪退-12

前言 在使用vscode的外部console时&#xff0c;会出现闪退现象&#xff0c;这是因为程序运行结束后&#xff0c;系统自动退出了终端&#xff08;终端机制决定的&#xff09;。我们可以在C程序结束后&#xff0c;使用system函数来暂停DOS终端系统&#xff0c;这样就可以完整地看…

中间件插件机制

一、插件 在mybatis一类中间件在处理的时候&#xff0c;提供了插件机制&#xff0c;类似于aop机制&#xff0c;可以在方法前、方法后进行拦截并且修改入参获得改变其方法的行为。那么调用的的方法应该也需要使用动态代理活动被插件进行aop的对象。

GD32F103硬件I2C0通讯

GD32F103的I2C模块有I2C0和I2C1;本程序使用I2C0功能模块; I2C0引脚复用和重映射: 当I2C0_REMAP0时,I2C0引脚复用功能,I2C0_SCL映射到PB6引脚,I2C0_SDA映射到PB7引脚; 当I2C0_REMAP1时,I2C0引脚重映射,I2C0_SCL映射到PB8引脚,I2C0_SDA映射到PB9引脚; I2C1引脚只有复用引脚: I2C…

Nevron Vision for .NET Crack

Nevron Vision for .NET Crack NET Vision是一个用于创建具有数据可视化功能的强大数据表示应用程序的套件。该套件具有用于.NET的Nevron Chart、用于.NET的Nevron Diagram和用于.NET的Nevron User Interface。精心设计的对象模型、众多功能和高质量的演示使复杂数据的可视化变…

观察级水下机器人使用系列之四二维前视声纳

本文主要讲观察级水下机器人Valor配套的二维前视声纳&#xff0c;它与超短基线定位、摄像头都是水下机器人导航的重要部件。二维声纳是Tritech公司生产的&#xff0c;型号为Gemini 720is。 ​编辑​ Gemini 720is主要技术参数见下表。 Gemini 720is通过一条蓝色的缆与机器人的…

Linux命令200例:wc用于统计文本文件中的字数、行数和字符数(常用)

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌。CSDN专家博主&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &…

字节C++后端面试总结

字节的面经,技术栈是 C++ 后端。 计算机网络 UDP和TCP区别 先说了概念一个是面向连接的基于字节流的可靠连接,一个是不需要连接的基于数据报的不可靠传输 然后说了几个小点,比如首部长度、应用场景、服务对象什么的。 补充: 还有一个很重要的点:UDP 的实时性比 TCP 好…

【培训】第一届深圳AI视觉项目研发与部署免费线下公开课启动!2023年8月底与我们相约,开启AI视觉之旅!...

人工智能&#xff08;AI&#xff09;时代来临&#xff0c;随着技术更新迭代&#xff0c;各行各业都因为深度学习技术而发生变革&#xff0c;技术人员的能力也需要不断更新。面向AI入门者&#xff0c;我们将在2023年下半年开启定期的线下教学&#xff0c;提供深度学习核心方法与…

网络安全进阶学习第十五课——Oracle SQL注入

文章目录 一、Oracle数据库介绍二、Oracle和MySQL的语法差异&#xff1a;三、Oracle的数据库结构四、Oracle的重点系统表五、Oracle权限分类1、系统权限2、实体权限3、管理角色 六、oracle常用信息查询方法七、联合查询注入1、order by 猜字段数量2、查数据库版本和用户名3、查…

MySQL之深入InnoDB存储引擎——redo日志

文章目录 一、为什么需要redo日志二、redo日志的类型1&#xff09;简单的redo日志类型2&#xff09;复杂的redo日志类型 三、Mini-Transaction四、redo日志的写入过程五、redo日志文件1、刷盘时机2、redo日志文件组 六、log sequence number1、lsn的引入2、flushed_to_disk_lsn…

MQTT消息传输过程,网络断开后,断线重连及订阅消息恢复

1&#xff0c;首先要在网络失败的地方进行client重连 2&#xff0c;一定要设置发送超时&#xff0c;默认是-1&#xff0c;是不断进行发送的&#xff0c;会被长阻塞在这里&#xff0c;单位是ms 3&#xff0c;参考链接 https://vimsky.com/examples/detail/java-method-org.ec…

实现 cpolar 内网穿透

简介 cpolar是一种安全的内网穿透云服务&#xff0c;可以将内网下的本地服务器通过安全隧道暴露至公网&#xff0c;使得公网用户可以正常访问内网服务。它是一款内网穿透软件&#xff0c;使用简单&#xff0c;只需一行命令即可将内网站点发布至公网&#xff0c;方便给客户演示…

【100天精通python】Day29:文件与IO操作_JSON文件处理

目录 专栏导读 一、XML文件概述 1. 标签和元素 2. 嵌套结构 3. 属性 4. 命名空间 5. CDATA节 6. 注释 7. 验证与验证语言 8. 扩展性 二、XML文件处理常见操作 1. 解析XML文件 2. 创建和编辑XML文件 3. 修改XML文件 4. 查询XML元素 5 遍历XML元素 6. 删除XML元…

嵌入式虚拟仿真实验教学平台之串口发送数据

嵌入式虚拟仿真实验教学平台课程系列 串口发送数据实验 课程内容 本实验使用 STM32 的串口发送数据。开始仿真后,打开串口监视器&#xff0c;串口监视器会打印出要发送的数据。 课程目标 学习配置使用GPIO功能学习配置使用复用功能学习配置使用UART功能 硬件设计 本课程…

扩散模型(DDPM)介绍

文章目录 扩散模型扩散过程前向过程逆向过程 网络结构 文章主要介绍了DDPM扩散模型&#xff0c;包含了详细的数学推导&#xff0c;可能公式有点多&#xff0c;但是只要能够耐心看完&#xff0c;相信会有一些收获的。好了下面进入正题。 扩散模型 扩散模型是一种新的生成模型&a…

FPGA纯verilog实现 LZMA 数据压缩,提供工程源码和技术支持

目录 1、前言2、我这儿已有的FPGA压缩算法方案3、FPGA LZMA数据压缩功能和性能4、FPGA LZMA 数据压缩设计方案输入输出接口描述数据处理流程LZ检索器数据同步LZMA 压缩器 为输出LZMA压缩流添加文件头 5、vivado仿真6、福利&#xff1a;工程代码的获取 1、前言 说到FPGA的应用&…