品牌营销型网站建设策划/做销售怎么和客户聊天

品牌营销型网站建设策划,做销售怎么和客户聊天,建设银行重置网站查询密码,广州哪里能买到真银目前接手的一个业务,应用不是用Activity/Fragment作为界面组件,而是用Window浮窗的形式显示,并且浮窗有很多种类型,每一种类型对应一类业务。那么怎么使用Jatpack的相关特性来设计架构并提高开发效率呢?分下面几个模块…

目前接手的一个业务,应用不是用Activity/Fragment作为界面组件,而是用Window浮窗的形式显示,并且浮窗有很多种类型,每一种类型对应一类业务。那么怎么使用Jatpack的相关特性来设计架构并提高开发效率呢?分下面几个模块做分析:

ViewModel

通常在使用ViewModel的时候,是跟Activity/Fragment对应起来的,分别实例化一个对象,这个时候,ViewModel是存在Activity的ViewModelStore里面的,而且会监听此Activity的生命周期,适时销毁。
但是在没有Activity的情况下,并且数据需要全局监听的时候,可以创建一个全局的ViewModel,设计成单例模式的类,它的生命周期是伴随应用的整个生命周期,如下:

object MainViewModel : ViewModel() {/*** 语音唤醒的状态*/var mWakeUp = MutableLiveData<Int>()
}

其实在这里,已经可以不用去实现ViewModel这个类了,定义一个普通的单例模式类就行了:

object MainViewModel {/*** 语音唤醒的状态*/var mWakeUp = MutableLiveData<Int>()
}

LiveData

MainViewModel中的LiveData主要分为两大类,一类是全局的数据监听,一类是针对于特定浮窗中使用到的数据。
第一类全局数据,可以使用全局监听,它的数据监听在应用整个生命周期都会有效:

// 全局检测,不带LifeCycleOwnerMainViewModel.mWakeUp.observeForever {Log.d(TAG, "wakeUp change $it")refreshWindowShown()}

第二类数据就是对应显示浮窗的数据,它应该是需要带生命周期的,即在弹窗显示的时候才更新数据,而在弹窗消失后,不用再更新数据,避免资源的浪费和内存的泄漏:

class ShowWindow(context: Context) : BaseWindow(context){MainViewModel.mWindowContent.observe(this) {Log.d(TAG, "receive mWindowContent$it")binding.contentTv.text = it}
}

这里就有一个问题,Activity是接入了LifeCycleOwner的,但是Window浮窗是没有接入的,而LiveData在订阅非全局的观察者时,需要有LifeCycleOwner参与,时候那应该怎么办呢?

LifeCycleOwner

LifeCycleOwner在LifeCycle的设计策略中扮演的是生命周期提供者的角色,一个UI组件想要接入到LifeCycle的一系列规则中,就需要实现LifeCycleOwner,比如我们熟知的ComponentActivity就是实现了LifecycleOwner,并且通过mLifecycleRegistry去做的生命周期的关联:

public class ComponentActivity extends Activity implementsLifecycleOwner,KeyEventDispatcher.Component {private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);@SuppressLint("RestrictedApi")@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);ReportFragment.injectIfNeededIn(this);}
}

高版本的SDK,是通过ReportFragment监听生命周期,然后再通过mLifecycleRegistry去设置。
同理,我们的Window浮窗想要去把自身的生命周期导入到LifeCycle中,也是需要实现LifecycleOwner,然后通过mLifecycleRegistry去关联生命周期,如下:

abstract class BaseWindow(val context : Context) : LifecycleOwner {private val lifecycleRegistry = LifecycleRegistry(this)open fun show() {lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START)}open fun hide() {lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP)}
}

即在show的时候,去开启生命周期,而在hide的时候去结束生命周期。这样,内部关联的LiveData在感知到Window浮窗的生命周期onStart后,就会开启数据的更新;在感知到onDestroy的时候去移除观察者,结束数据更新,如下:

// 处理STARTED事件
@Override
boolean shouldBeActive() {return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);}// 处理 DESTROYED事件
@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {removeObserver(mObserver); // 自动解绑return;}// 其他状态处理...
}

ViewBinding

ViewBinding在Window浮窗的使用没有任何障碍,通过配置gradle打开ViewBinding功能:

buildFeatures {viewBinding = true}

然后就可以在对应的浮窗中使用ViewBinding:

class ShowWindow(context: Context) : BaseWindow(context){private val binding : ShowwindowBinding by lazy { ShowwindowBinding.inflate(LayoutInflater.from(context)) }
}

这里的context是传入的ApplicationContext,同样是没问题的。
这里想说一下基类和子类怎么处理Viewbinding。比如这一类浮窗中,它们有一些共同的界面逻辑,只是其中一块显示区域的内容有差距。这时候,我们可以抽取一个BaseWindow,并在BaseWindow中实现公共的UI和逻辑,同时在界面布局中预留出子类的显示区域。这样在BaseWindow和子类Window都可以使用ViewBinding。
也可以理解为,只要有一个layout布局文件,就对应一个ViewBinding类。具体的实现如下:
Base类的布局文件预留一个子类的内容显示区域,不同的子类会填充不同的内容:

<FrameLayoutandroid:id="@+id/content_layout"android:layout_width="870dp"android:layout_height="match_parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintRight_toRightOf="parent"/>

Base类的代码实现:

abstract class BaseWindow(context: Context){
private val binding : BaseWindowBinding by lazy { BaseWindowBinding.inflate(LayoutInflater.from(context)) }override fun getView(): View {if (binding.contentLayout.childCount == 0) {binding.contentLayout.addView(getContentLayout())}return binding.root}//预留给子类实现abstract fun getContentLayout() : View

在子类的实现中,使用ViewBindiing加载自己的布局模块就好,并把自己的根布局通过getContentLayout方法返回。

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

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

相关文章

基于WebRtc,GB28181,Rtsp/Rtmp,SIP,JT1078,H265/WEB融合视频会议接入方案

智能融合视频会议系统方案—多协议、多场景、全兼容的一站式视频协作平台 OvMeet,LiveMeet针对用户​核心痛点实现功能与用户价值 &#xff0c;Web平台实现MCU多协议&#xff0c;H265/H264等不同编码监控&#xff0c;直播&#xff0c;会议&#xff0c;调度资源统一融合在一套界…

卷积神经网络 - 汇聚层

卷积神经网络一般由卷积层、汇聚层和全连接层构成&#xff0c;本文我们来学习汇聚层。 汇聚层(Pooling Layer)也叫子采样层(Subsampling Layer)&#xff0c;其作用是进 行特征选择&#xff0c;降低特征数量&#xff0c;从而减少参数数量。 卷积层虽然可以显著减少网络中连接的…

vue使用element-ui自定义样式思路分享【实操】

前言 在使用第三方组件时&#xff0c;有时候组件提供的默认样式不满足我们的实际需求&#xff0c;需要对默认样式进行调整&#xff0c;这就需要用到样式穿透。本篇文章以vue3使用element-ui的Tabs组件&#xff0c;对Tabs组件的添加按钮样式进行客制化为例。 确定需要修改的组…

【工具分享】vscode+deepseek的接入与使用

目录 第一章 前言 第二章 获取Deepseek APIKEY 2.1 登录与充值 2.2 创建API key 第三章 vscode接入deepseek并使用 3.1 vscode接入deepseek 3.2 vscode使用deepseek 第一章 前言 deepseek刚出来时有一段时间余额无法充值&#xff0c;导致小编没法给大家发完整的流程&…

【蓝桥杯速成】| 9.回溯升级

题目一&#xff1a;组合综合 问题描述 39. 组合总和 - 力扣&#xff08;LeetCode&#xff09; 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返…

【C++进阶】深入探索类型转换

目录 一、C语言中的类型转换 1.1 隐式类型转换 1.2. 显式类型转换 1.3.C语言类型转换的局限性 二、C 类型转换四剑客 2.1 static_cast&#xff1a;静态类型转换&#xff08;编译期检查&#xff09; 2.2 dynamic_cast&#xff1a;动态类型转换&#xff08;运行时检查&…

代码随想录_动态规划

代码随想录 动态规划 509.斐波那契数 509. 斐波那契数 斐波那契数 &#xff08;通常用 F(n) 表示&#xff09;形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始&#xff0c;后面的每一项数字都是前面两项数字的和。也就是&#xff1a; F(0) 0&#xff0c;F(1) 1 F(n…

计算机基础:编码03,根据十进制数,求其原码

专栏导航 本节文章分别属于《Win32 学习笔记》和《MFC 学习笔记》两个专栏&#xff0c;故划分为两个专栏导航。读者可以自行选择前往哪个专栏。 &#xff08;一&#xff09;WIn32 专栏导航 上一篇&#xff1a;计算机基础&#xff1a;编码02&#xff0c;有符号数编码&#xf…

设计模式(创建型)-单例模式

摘要 在软件开发的世界里&#xff0c;设计模式是开发者们智慧的结晶&#xff0c;它们为解决常见问题提供了经过验证的通用方案。单例模式作为一种基础且常用的设计模式&#xff0c;在许多场景中发挥着关键作用。本文将深入探讨单例模式的定义、实现方式、应用场景以及可…

基于FPGA频率、幅度、相位可调的任意函数发生器(DDS)实现

基于FPGA实现频率、幅度、相位可调的DDS 1 摘要 直接数字合成器( DDS ) 是一种通过生成数字形式的时变信号并进行数模转换来产生模拟波形(通常为正弦波)的方法,它通过数字方式直接合成信号,而不是通过模拟信号生成技术。DDS主要被应用于信号生成、通信系统中的本振、函…

本地JAR批量传私服

在有网络隔离的环境下&#xff0c;Maven项目如果没有搭建私服就得把用到的通用组件通过U盘在每个组员间拷贝来拷贝去。非常的麻烦跟低效。搭建私服&#xff0c;如果通用组件很多的时候手工一个一个上传更是非常的麻烦跟低效&#xff1b; 我就遇上这问题&#xff0c;跟A公司合作…

【ROS实战】02-ROS架构介绍

1. 简介 你是否曾有过这样的疑问&#xff1a;我按照文档安装了ROS&#xff0c;依照要求写了一些示例节点&#xff08;node&#xff09;、消息&#xff08;msg&#xff09;和话题&#xff08;topic&#xff09;&#xff0c;但觉得过程既麻烦又繁琐。也许你开始怀疑&#xff1a;…

LeetCode算法题(Go语言实现)_07

题目 给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复…

网络华为HCIA+HCIP 网络编程自动化

telnetlib介绍 telnetlib是Python标准库中的模块。它提供了实现Telnet功能的类telnetlib.Telnet。这里通过调用telnetlib.Telnet类里的不同方法实现不同功能。 配置云

查看GPU型号、大小;CPU型号、个数、核数、内存

GPU型号、大小 nvidia-smiCPU型号 cat /proc/cpuinfo | grep model name | uniqCPU个数 cat /proc/cpuinfo | grep "physical id" | uniq | wc -lCPU核数 cat /proc/cpuinfo | grep "cpu cores" | uniqCPU内存 cat /proc/meminfo | grep MemTotal参考…

Android Handler 通过线程安全的 MessageQueue 和底层唤醒机制实现跨线程通信

目录 一、MessageQueue 的线程安全实现 1. 消息队列的同步锁&#xff08;synchronized&#xff09; 2. 消息顺序与延时处理 二、底层唤醒机制&#xff1a;从 Java 到 Linux 内核 1. 消息插入后的唤醒逻辑 2. Native 层实现&#xff08;基于 Linux 的 eventfd 和 epoll&am…

MySQL中的锁机制:从全局锁到行级锁

目录 1. 锁的基本概念 2. 全局锁 2.1 全局锁的定义 2.2 全局锁的类型 2.3 全局锁的使用场景 2.4 全局锁的实现方式 2.5 全局锁的优缺点 2.6 全局锁的优化 3. 表级锁 3.1 表级锁的类型 3.2 表级锁的使用场景 3.3 表级锁的优缺点 4. 意向锁&#xff08;Intention Lo…

基于WebRTC的嵌入式音视频通话SDK:EasyRTC跨平台兼容性技术架构实时通信的底层实现

EasyRTC的核心架构围绕WebRTC技术构建&#xff0c;同时通过扩展信令服务、媒体服务器和NAT穿透机制&#xff0c;解决了WebRTC在实际部署中的痛点。其架构可以分为以下几个核心模块&#xff1a; 1&#xff09;WebRTC基础层 媒体捕获与处理&#xff1a;通过getUserMediaAPI获取…

微服务架构中的API网关:Spring Cloud与Kong/Traefik等方案对比

微服务架构中的API网关&#xff1a;Spring Cloud与Kong/Traefik等方案对比 一、API 网关的概念二、API 网关的主要功能2.1 统一入口与路由转发2.2 安全与权限控制2.3 流量管理与容错2.4 API 管理与聚合2.5 监控与日志2.5 协议转换与适配2.6 控制平面与配置管理 三、API 网关选型…

NewStar CTF web wp

文章目录 week1headach3会赢吗智械危机谢谢皮蛋PangBai 过家家&#xff08;1&#xff09; week3include meblindsql1臭皮的计算机臭皮踩踩背这照片是你吗 week4Pangbai过家家四blindsql2chocolateezcmsssezpollute隐藏的密码 weeek5pangbai过家家(5)redissqlshell臭皮吹泡泡臭皮…