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

Windows环境下实现设计模式——状态模式(JAVA版)

我是荔园微风,作为一名在IT界整整25年的老兵,今天总结一下Windows环境下如何编程实现状态模式(设计模式)。

不知道大家有没有这样的感觉,看了一大堆编程和设计模式的书,却还是很难理解设计模式,无从下手。为什么?因为你看的都是理论书籍。

我今天就在Windows操作系统上安装好JAVA的IDE编程工具,并用JAVA语言来实现一个状态模式,真实的实现一个,你看懂代码后,自然就明白了。

状态模式State Pattern(行为型设计模式)

定义:允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。

上面定义听懂了吗?莫名其妙看不懂对吧。所以我们还是来看看实现生活中的例子。

在日常生活中,人们总是有些各种喜怒哀乐的表情,而且这四种状态还会互相转化,包括人在内,很多事物都具有多种状态,而且在不同状态下会具有不同的行为,这些状态在特定条件下还将发生相互转换。而状态模式就是要模拟这种同一事物存在多种状态但又会变化转化的情况。状态模式是一种较为复杂的设计模式,它用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题。当系统中的某个对象存在多个状态,这些状态之间可以进行转换,而且对象在不同状态下行为不相同时可以使用状态模式。

在软件系统中,有些对象具有多种状态,这些状态在某些情况下能够相互转换,而且对象在不同的状态下也将具有不同的行为。通常可以使用复杂的条件判断语句if else之类来进行状态判断和转换操作,但这样会导致代码的可维护性和灵活性下降。

状态模式用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题。当系统中某个对象存在多个状态,这些状态之间可以进行转换,而且对象在不同状态下行为不相同时可以使用状态模式。状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化,对于客户端而言,无须关心对象状态的转换以及对象所处的当前状态,无论对于何种状态的对象,客户端都可以一致处理。

在状态模式结构图中包含如下三个角色:Context(环境类)、State(抽象状态类)、ConcreteState(具体状态类)。环境类又称为上下文类,它是拥有多种状态的对象。由于环境类的状态存在多样性且在不同状态下对象的行为有所不同,因此将状态独立出去形成单独的状态类。在环境类中维护一个抽象状态类State的实例,这个实例定义当前状态,在具体实现时,它是一个State子类的对象。抽象状态类用于定义一个接口以封装与环境类的一个特定状态相关的行为,在抽象状态类中声明了各种不同状态对应的方法,而在其子类中实现类这些方法,由于不同状态下对象的行为可能不同,因此在不同子类中方法的实现可能存在不同,相同的方法可以写在抽象状态类中。具体状态类是抽象状态类的子类,每一个子类实现一个与环境类的一个状态相关的行为,每一个具体状态类对应环境的一个具体状态,不同的具体状态类其行为有所不同。

JAVA代码

public abstract class State {//声明抽象业务方法,不同的具体状态类可以不同的实现public abstract void handle();
}public class ConcreteState extends State {public void handle() {//方法具体实现代码}
}public class Context {private State state; //维持一个对抽象状态对象的引用private int value; //其他属性值,该属性值的变化可能会导致对象状态发生变化//设置状态对象public void setState(State state) {this.state = state;}public void request() {//其他代码state.handle(); //调用状态对象的业务方法//其他代码}
}

Context(环境类)实际上是真正拥有状态的对象,这个模式的主要精神就是将Context(环境类)中与状态有关的代码提取出来封装到专门的状态类中。在状态模式结构图中,在Context中定义了一个State对象。Context(环境类)与抽象状态类State之间存在单向关联关系,也可能存在依赖或者其他关联关系。

好,下面是关键的内容了,这部分是这个模式和其他设计模式一个很大的不同点,也是此模式复杂的地方,也就是在状态模式的使用过程中,一个对象的状态之间还可以进行相互转换,通常有两种实现状态转换的方式:

(1) 统一由环境类来负责状态之间的转换,此时,环境类还充当了状态管理器(State Manager)角色,在环境类的业务方法中通过对某些属性值的判断if else之类实现状态转换,还可以提供一个专门的方法用于实现属性判断和状态转换,如下所示:

public void changeState() {//判断属性值,根据属性值进行状态转换if (value == 0) {this.setState(new ConcreteStateA());}else if (value == 1) {this.setState(new ConcreteStateB());}......
}

(2) 由具体状态类来负责状态之间的转换,可以在具体状态类的业务方法中判断环境类的某些属性值再根据情况为环境类设置新的状态对象,实现状态转换,同样,也可以提供一个专门的方法来负责属性值的判断和状态转换。此时,状态类与环境类之间就将存在依赖或关联关系,因为状态类需要访问环境类中的属性值,如下所示:

public void changeState(Context su) {//根据环境对象中的属性值进行状态转换if (su.getValue() == 1) {su.setState(new ConcreteStateB());}else if (su.getValue() == 2) {su.setState(new ConcreteStateC());}......
}

应用实例

某金融理财手机APP具有理财功能,每位用户在其中会开通个人账户(Account),APP用户账户存在三种状态,在不同状态下账户存在不同的行为,如果账户中余额大于等于0,则账户的状态为正常状态(Normal State),此时用户既可以向该账户存款也可以从该账户取款; 如果账户中余额小于0,并且大于-10000,则账户的状态为透支状态(Overdraft State),此时用户既可以向该账户存款也可以从该账户取款,但需要按天计算利息;如果账户中余额等于-10000,那么账户的状态为受限状态(Restricted State),此时用户只能向该账户存款,不能再从中取款,同时也将按天计算利息。还有最后一种情况,如果取款导致金额小于-10000元了怎么办?我们这里要规定一下,如果小于这个数,马上宣布不正常状态不准用户操作。Check()用于在每一次执行存款和取款操作后根据余额来判断是否要进行状态转换并实现状态转换,相同的方法在不同的状态中可能会有不同的实现。为了实现不同状态下对象的各种行为以及对象状态之间的相互转化。

(1)Account:银行账户,环境类

package designpatterns.state;public class Account {private AccountState state;   //维持一个对抽象状态对象的引用private String owner;   //开户名private double balance = 0;   //账户余额public Account(String owner,double init) {this.owner = owner;this.balance = init;this.state = new NormalState(this); //设置初始状态System.out.println(this.owner + "开户,余额为" + this.balance);    }public double getBalance() {return this.balance;}public void setBalance(double balance) {this.balance = balance;}public void setState(AccountState state) {this.state = state;}public void deposit(double amount) {System.out.println(this.owner + "存款" + amount);state.deposit(amount); //调用状态对象的deposit()方法System.out.println("余额为"+ this.balance);System.out.println("帐户状态为"+ this.state.getClass().getName());}public void withdraw(double amount) {System.out.println(this.owner + "取款" + amount);state.withdraw(amount); //调用状态对象的withdraw()方法System.out.println("余额为"+ this.balance);System.out.println("帐户状态为"+ this. state.getClass().getName());        }public void Interest(){state.Interest(); //调用状态对象的Interest()方法}
}

(2)AccountState:账户状态类,抽象状态类

package designpatterns.state;public abstract class AccountState {protected Account cp;public abstract void deposit(double amount);public abstract void withdraw(double amount);public abstract void Interest();public abstract void Check();
}

(3)NormalState:正常状态类

package designpatterns.state;public class NormalState extends AccountState {public NormalState(Account cp) {this.cp = cp;}public NormalState(AccountState state) {this.cp = state.cp;}public void deposit(double amount) {cp.setBalance(cp.getBalance() + amount);Check();}public void withdraw(double amount) {cp.setBalance(cp.getBalance() - amount);Check();}public void Interest(){System.out.println("正常状态");}//状态转换public void Check() {if (cp.getBalance() > -10000 && cp.getBalance() <= 0) {cp.setState(new OverdraftState(this));}else if (cp.getBalance() == -10000) {cp.setState(new RestrictedState(this));}else if (cp.getBalance() < -10000) {System.out.println("不正常状态");}    }   
}  

(4)OverdraftState:透支状态类

package designpatterns.state;public class OverdraftState extends AccountState {public OverdraftState(AccountState state) {this.cp = state.cp;}public void deposit(double amount) {cp.setBalance(cp.getBalance() + amount);Check();}public void withdraw(double amount) {cp.setBalance(cp.getBalance() - amount);Check();}public void Interest(){System.out.println("利息数额");}//状态转换public void Check() {if (cp.getBalance() > 0) {cp.setState(new NormalState(this));}else if (cp.getBalance() == -10000) {cp.setState(new RestrictedState(this));}else if (cp.getBalance() < -10000) {System.out.println("不正常状态");}    }   
}  

(5)RestrictedState:透支状态类

package designpatterns.state;public class RestrictedState extends AccountState {public OverdraftState(AccountState state) {this.cp = state.cp;}public void deposit(double amount) {cp.setBalance(cp.getBalance() + amount);Check();}public void withdraw(double amount) {System.out.println("不能");}public void Interest(){System.out.println("利息数额");}//状态转换public void Check() {if (cp.getBalance() > 0) {cp.setState(new NormalState(this));}else if (cp.getBalance() > -10000) {cp.setState(new OverdraftState(this));}}   
}  

(6)Client:客户端测试类

package designpatterns.state;public class Client {public static void main(String args[]) {Account cp = new Account("小牛",0.0);cp.deposit(5000);cp.withdraw(10000);cp.deposit(6000);cp.withdraw(4000);cp.Interest();}
}

这篇设计模式文章是我写的最累的一篇了,写到这里已经很晚了,实在写不动了。输出结果大家自行推理就是了。无非就是随着用户又取钱又存钱的导致银行帐户出现各类状态转换问题。

状态模式将一个对象在不同状态下的不同行为封装在一个个状态类中,通过设置不同的状态对象可以让环境对象拥有不同的行为,而状态转换的细节对于客户端而言是透明的,方便了客户端的使用。在实际开发中,状态模式具有较高的使用频率,在工作流和游戏开发中状态模式都得到了广泛的应用,例如公文状态的转换、游戏中角色的升级等。

各位小伙伴,这次我们就说到这里,下次我们再深入研究windows环境下的各类设计模式实现。

作者简介:荔园微风,1981年生,高级工程师,浙大工学硕士,软件工程项目主管,做过程序员、软件设计师、系统架构师,早期的Windows程序员,Visual Studio忠实用户,C/C++使用者,是一位在计算机界学习、拼搏、奋斗了25年的老将,经历了UNIX时代、桌面WIN32时代、Web应用时代、云计算时代、手机安卓时代、大数据时代、ICT时代、AI深度学习时代、智能机器时代,我不知道未来还会有什么时代,只记得这一路走来,充满着艰辛与收获,愿同大家一起走下去,充满希望的走下去。

相关文章:

Windows环境下实现设计模式——状态模式(JAVA版)

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天总结一下Windows环境下如何编程实现状态模式&#xff08;设计模式&#xff09;。不知道大家有没有这样的感觉&#xff0c;看了一大堆编程和设计模式的书&#xff0c;却还是很难理解设计模式&#xff0c;无…...

【总结】多个条件排序(pii/struct/bool)

目录 pii struct bool pii 现在小龙同学要吃掉它们&#xff0c;已知他有n颗苹果&#xff0c;并且打算每天吃一个。 但是古人云&#xff0c;早上金苹果&#xff0c;晚上毒苹果。由此可见&#xff0c;早上吃苹果和晚上吃苹果的效果是不一样的。 已知小龙同学在第 i 天早上吃苹果能…...

基于stm32mp157 linux开发板ARM裸机开发教程Cortex-A7 开发环境搭建(连载中)

前言&#xff1a;目前针对ARM Cortex-A7裸机开发文档及视频进行了二次升级持续更新中&#xff0c;使其内容更加丰富&#xff0c;讲解更加细致&#xff0c;全文所使用的开发平台均为华清远见FS-MP1A开发板&#xff08;STM32MP157开发板&#xff09;针对对FS-MP1A开发板&#xff…...

最适合游戏开发的语言是什么?

建议初学者学习主流的开发技术 主流开发技术有大量成熟的教程、很多可以交流的学习者、及时的学习反馈等&#xff1b;技术的内里基本都是相同的&#xff0c;学习主流技术的经验、知识可以更好更快地疏通学习新知识和技术。 因此&#xff0c;对C#或者C二选一进行学习较好。 Un…...

C语言刷题(7)(字符串旋转问题)——“C”

各位CSDN的uu们你们好呀&#xff0c;今天&#xff0c;小雅兰的内容依旧是复习之前的知识点&#xff0c;那么&#xff0c;就是做一道小小的题目啦&#xff0c;下面&#xff0c;让我们进入C语言的世界吧 实现一个函数&#xff0c;可以左旋字符串中的k个字符。 例如&#xff1a; A…...

有趣且重要的JS知识合集(18)浏览器实现前端录音功能

1、主题描述 兼容多个浏览器下的前端录音功能&#xff0c;实现六大录音功能&#xff1a; 1、开始录音 2、暂停录音 3、继续录音 4、结束录音 5、播放录音 6、上传录音 2、示例功能 初始状态&#xff1a; 开始录音&#xff1a; 结束录音&#xff1a; 录音流程 &#xf…...

面试官:聊聊你知道的跨域解决方案

跨域是开发中经常会遇到的一个场景&#xff0c;也是面试中经常会讨论的一个问题。掌握常见的跨域解决方案及其背后的原理&#xff0c;不仅可以提高我们的开发效率&#xff0c;还能在面试中表现的更加游刃有余。 因此今天就来和大家从前端的角度来聊聊解决跨域常见的几种方式。…...

SpringCloud五大核心组件

Consul 等&#xff0c;提供了搭建分布式系统及微服务常用的工具&#xff0c;如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性token、全局锁、选主、分布式会话和集群状态等&#xff0c;满足了构建微服务所需的所有解决方案。 服务发现——Netflix Eureka …...

Verilog HDL语言入门(二)

强烈建议用同步设计2.在设计时总是记住时序问题3.在一个设计开始就要考虑到地电平或高电平复位、同步或异步复位、上升沿或下降沿触发等问题&#xff0c;在所有模块中都要遵守它4.在不同的情况下用if和case&#xff0c;最好少用if的多层嵌套&#xff08;1层或2层比较合适&#…...

Simpleperf详细使用

一、Simpleperf介绍 Simpleperf是一个强大的命令行工具&#xff0c;它包含在NDK中&#xff0c;可以帮助我们分析应用的CPU性能。Simpleperf可以帮助我们找到应用的热点&#xff0c;而热点往往与性能问题相关&#xff0c;这样我们就可以分析修复热点源。 如果您更喜欢使用命令…...

【算法基础】二分图(染色法 匈牙利算法)

一、二分图 1. 染色法 一个图是二分图,当且仅当,图中不含奇数环。在判别一个图是否为二分图⑩,其实相当于染色问题,每条边的两个点必须是不同的颜色,一共有两种颜色,如果染色过程中出现矛盾,则说明不是二分图。 for i = 1 to n:if i 未染色DFS(i, 1); //将i号点染色未…...

Caputo 分数阶微分方程-慢扩散方程初边值问题基于L1 逼近的空间二阶方法及其Matlab程序实现

2.3.3 Caputo 分数阶一维问题基于 L1 逼近的空间二阶方法 考虑如下时间分数阶慢扩散方程初边值问题 { 0 C D t α u ( x , t ) = u...

I.MX6ULL_Linux_驱动篇(29) GPIO驱动

Linux 下的任何外设驱动&#xff0c;最终都是要配置相应的硬件寄存器。所以本篇的 LED 灯驱动最终也是对 I.MX6ULL 的 IO 口进行配置&#xff0c;与裸机实验不同的是&#xff0c;在 Linux 下编写驱动要符合 Linux 的驱动框架。I.MX6U-ALPHA 开发板上的 LED 连接到 I.MX6ULL 的 …...

jupyter的安装和使用

目录 ❤ Jupyter Notebook是什么&#xff1f; notebook jupyter 简介 notebook jupyter 组成 网页应用 文档 主要特点 ❤ jupyter notebook的安装 notebook jupyter 安装有两种途径 1.通过Anaconda进行安装 2.通过pip进行安装 启动jupyter notebook ❤ jupyter …...

Springboot新手开发 Cloud篇

前言&#xff1a; &#x1f44f;作者简介&#xff1a;我是笑霸final&#xff0c;一名热爱技术的在校学生。 &#x1f4dd;个人主页&#xff1a;个人主页1 || 笑霸final的主页2 &#x1f4d5;系列专栏&#xff1a;后端专栏 &#x1f4e7;如果文章知识点有错误的地方&#xff0c;…...

Linux:函数指针做函数参数

#include <stdio.h> #include <stdlib.h> //创建带有函数指针做参数的函数框架api //调用者要先实现回调函数 //调用者再去调用函数框架 //所谓的回调是指 调用者去调用一个带有函数指针做参数的函数框架&#xff0c;函数框架反过来要调用调用者提供的回调函数 …...

Vue3(递归组件) + 原生Table 实现树结构复杂表格

一、递归组件 什么是递归&#xff0c;Javascript中经常能接触到递归函数。也就是函数自己调用自己。那对于组件来说也是一样的逻辑。平时工作中见得最多应该就是菜单组件&#xff0c;大部分系统里面的都是递归组件。文章中我做了按需引入的配置&#xff0c;所以看不到我引用组…...

ArrayList底层源码解析

Java源码系列&#xff1a;下方连接 http://t.csdn.cn/Nwzed 文章目录前言一、**ArrayList底层结构和源码分析**无参构造调用创建ArrayList集合无参构造总结&#xff1a;发文3个工作日后 up 会把总结放入前言部分&#xff0c;但也诚邀读者总结&#xff0c;可放入评论区有参构造…...

python:DIY字符画的程序使用说明.doc

目录开发环境要求运行方法具体的操作步骤如下&#xff1a;代码示例源码及运行程序下载地址开发环境要求 本系统的软件开发及运行环境具体如下。 操作系统&#xff1a;Windows 7、Windows 10。 Python版本&#xff1a;Python 3.7.0。 开发工具&#xff1a;Python IDLE。 …...

【Python/Opencv】图像权重加法函数:cv2.addWeighted()详解

【Python/Opencv】图像权重加法函数&#xff1a;cv2.addWeighted()详解 文章目录【Python/Opencv】图像权重加法函数&#xff1a;cv2.addWeighted()详解1. 介绍2. API3. 代码示例与效果3.1 代码3.2 效果4. 参考1. 介绍 在OpenCV图像加法cv2.add函数详解详细介绍了图像的加法运…...

容器的老祖宗LXC和Docker的关系

一、什么是LXC&#xff1f; LXC&#xff08;Linux Container的缩写&#xff09;是一个基于Linux内核的容器虚拟化技术&#xff0c;它提供了一种轻量级、快速、简便的方式来创建和管理系统容器。与传统虚拟化技术不同&#xff0c;LXC并不会模拟硬件&#xff0c;而是利用Linux内…...

Webpack迁移Rspack速攻实战教程(前瞻版)

前言 rspack 即将开源&#xff0c;但社区中不乏有已经落地的 case &#xff0c;比如 rspack-migration-showcase 、 modern.js 等。 基于此&#xff0c;本文将介绍如何迁移一个近似于 CRA&#xff08; create-react-app &#xff09; 的项目到 rspack 。 在阅读本文前&#…...

一行代码“黑”掉任意网站

文章目录只需一行代码&#xff0c;轻轻一点就可以把任意网站变成暗黑模式。 首先我们先做一个实验&#xff0c;在任意网站中&#xff0c;打开浏览器开发者工具(F12)&#xff0c;在 C1onsole 控制台输入如下代码并回车&#xff1a; document.documentElement.style.filterinve…...

51单片机入门 -驱动 8x8 LED 点阵屏

硬件型号、软件版本、以及烧录流程 操作系统&#xff1a;Windows 10 x84-64单片机&#xff1a;STC89C52RC编译器&#xff1a;SDCC烧录软件&#xff1a;stcgal 1.6开发板&#xff1a;普中51单片机开发板A2套件&#xff08;2022&#xff09; 在 VS Code 中新建项目到烧录的过程…...

Xinlinx zynq7045国产替代 FMQL45T900全国产化 ARM 核心板+扩展板

TES745D 是一款基于 FMQL45T900 的全国产化 ARM 核心板。该核心板将 FMQL45T900&#xff08;与XC7Z045-2FFG900I 兼容&#xff09;的最小系统集成在了一个 87*117mm 的核心板上&#xff0c;可以作为一个核心模块&#xff0c;进行功能性扩展&#xff0c;能够快速的搭建起一个信号…...

硬刚ChatGPT!文心一言能否为百度止颓?中国版ChatGPT“狂飙”的机会在哪儿?

文章目录目录产品背景发展历程科技简介主要功能合作伙伴结语文心一言 &#xff08;英文名&#xff1a;ERNIE Bot&#xff09; *是百度基于文心大模型技术推出的生成式对话产品&#xff0c;被外界誉为“中国版ChatGPT”&#xff0c;将于2023年3月份面向公众开放。 [40] 百度在人…...

Python 异步: 在非阻塞子进程中运行命令(19)

动动发财的小手&#xff0c;点个赞吧&#xff01; 我们可以从 asyncio 执行命令。该命令将在我们可以使用非阻塞 I/O 写入和读取的子进程中运行。 1. 什么是 asyncio.subprocess.Process asyncio.subprocess.Process 类提供了由 asyncio 运行的子进程的表示。它在 asyncio 程序…...

蓝桥杯嵌入式第五课--输入捕获

前言输入捕获的考题十分明确&#xff0c;就是测量输入脉冲波形的占空比和频率&#xff0c;对我们的板子而言&#xff0c;就是检测板载的两个信号发生器产生的信号&#xff1a;具体来说就是使用PA15和PB4来做输入捕获。输入捕获原理简介输入捕获能够对输入信号的上升沿和下降沿进…...

Spring事务和事务传播机制

目录 Spring中事务的实现 1、通过代码的方式手动实现事务 2、通过注解的方式实现声明式事务 2.1、Transactional作用范围 2.2、Transactional参数说明 2.3、注意事项 2.4、Transactional工作原理 事务隔离级别 1、事务特性 2、Spring中设置事务隔离级别 2.1、MySQL事…...

基于OpenCV+CUDA实时视频抠绿、背景合成以及抠绿算法小结

一、关于抠绿 百度百科上描述抠绿“抠绿是指在摄影或摄像时,以绿色为背景进行拍摄,在后期制作时使用特技机的“色键”将绿色背景抠去,改换其他更理想的背景的技术。”绿幕的使用已经非常普遍,大到好莱坞大片,小到自媒体的节目,一些商业娱乐场景,几乎都用使用。但是很多非…...

网站一般如何做搜索功能/搜索引擎广告形式有

VLOOKUP函数在日常工作中十分常见&#xff0c;以至于你要是没用过VLOOKUP函数&#xff0c;你都不好意思说你懂EXCEL。 一般情况下&#xff0c;我们需要在源数据中查找某个指定列的数据&#xff0c;就会用到VLOOKUP函数&#xff08;如果是指定行的数据&#xff0c;则用HLOOKUP函…...

本地搭建网站网站后台/爱站网官网

直接上代码&#xff0c;下注释掉的代码为导出Excel代码&#xff0c;因远程机器上未安装excel&#xff0c;所以后改为csv。 dataGridView能直接粘贴数据到excel,同样也可以由excel粘贴到dataGridView&#xff0c; 利用exe粘贴数据直接更新能避免人为因素而导致的错误 using S…...

宿州网站开发/app软件推广怎么做

人生四问别让自己跟着思维走世间万物&#xff0c;存在即合理--2018年终总结转载于:https://www.cnblogs.com/skyflask/p/8319841.html...

java开发手机网站开发/电商培训机构有哪些哪家比较好

字符串格式化字符串格式化使用字符串格式化操作符即百分号%来实现。在%的左侧放置一个字符串(格式化字符串)&#xff0c;而在右侧则放置希望格式化的值&#xff0c;可以使用一个值&#xff0c;如一个字符串或者数字&#xff0c;也可以使用多个值的元组或者字典&#xff0c;如&g…...

重庆网站建设服务价格/广东东莞疫情最新消息今天又封了

格式描述&#xff1a; 这个作业属于哪个课程 课程的链接 这个作业要求在哪里 作业要求的链接 我在这个课程的目标是 正视自己学软件工程的初心 从迷茫中找到适合自己的方向 学会独立思考的能力&#xff0c;从大一到现在一直都是浑浑噩噩的&#xff0c;完成的作业大多参考着…...

做生存曲线的网站/国外seo大神

来张简单的效果图:scale.gif问题引出半年前开始接触Android列表播放短视频开发是从 VideoPlayerManager 这里开始的。该库核心思路:1.使用TextureView嵌套在Item View里面作为视频渲染2.将视频的生命周期全部在子线程队列执行&#xff0c;然后post到主线程&#xff0c;避免ANR以…...