自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(122)
  • 收藏
  • 关注

原创 MemoryAnalyzer(mat)安装报错:version1.8.0 of the jvm is not suitable for this product

3、配置完成后,还要修改下MemoryAnalyzer.ini这个配置文件,打开后加入下面语句,第二行是你的jdk安装路径,到bin这一级就够了。4、点击MemoryAnalyzer.exe可启动MAT分析工具。大家可以根据自己的系统选择版本,点击安装下。

2023-12-04 10:35:07 3969 5

原创 MediaPlayer+TextureView实现视频播放功能

3、初始化TextureView,并设置监听,需求需要给给TextureView加一个圆角,角度是16。2、初始化视频资源,这里把需要播放的视频集成在应用中,位置放在res/raw下。前面写一些基础知识的学习,这篇写个小demo,实现视频循环播放功能。这个demo只是简单实现,具体播放最好放子线程进行。4、初始化MediaPalyer播放器。

2023-10-29 10:07:53 634

原创 MediaPlayer

prepared()方法直接进入Parpared状态,preparedAsync()方法是异步执行,会先进入Preparing状态,播放引擎准备完毕后会通过OnPreparedListener.onPrepared()回调方法通知进入Prepared状态。:当视频播放完成之后,如果设置setLooping()为false,并且设置了回调setOnCompletionListener(),会执行OnCompletion.onCompletion()方法,在回调后进入PlaybackCompleted状态。

2023-10-29 10:06:39 468

原创 TextureView和SurfaceView

这使得SurfaceView的绘制和刷新可以在单独的线程中进行,从而大大提高效率,并且SurfaceView窗口刷新的时候不需要重绘应用程序的窗口(android普通窗口的视图绘制机制是一层一层的,任何一个子元素或者是局部的刷新都会导致整个视图结构全部重绘一次,因此效率非常低下,不过满足普通应用界面的需求还是绰绰有余)。Surface对应了一块屏幕的缓冲区,每一个window对应一个Surface,任何View都是画在Surface上的,传统的View共享一块屏幕缓冲区,所有的绘制都必须在UI线程上进行。

2023-10-29 10:05:24 446

原创 Android蓝牙 - 常用蓝牙配置文件

举个例子:免提配置文件。此规格用于许可单个远程控制设备(或其它设备)控制所有用户可以接入的A/V设备。用于播放音乐,音频单向输出,允许传输立体声音频信号,音质与有线耳机相当,支持A2DP的耳机就是蓝牙立体声耳机。HSP(Head Set Profile):这是最常用的配置,为当前流行支持蓝牙耳机与移动电话使用,OPP(Object Push Profile):对象存储规范,最为常见的,连接和配置好后,耳机可以作为远程设备的音频输入和输出接口。,让车载免提装置可以控制电话,如接听、挂断、拒接、语音拨号等。

2023-10-29 10:00:19 591

原创 Android蓝牙 - 经典蓝牙BT

代表了移动设备的本地的蓝牙适配器, 通过该蓝牙适配器可以对蓝牙进行基本操作, 例如 : 启动设备发现,获取已配对设备,通过mac蓝牙地址获取蓝牙设备等。蓝牙发展至今经历了多个版本的更新,其中,将1.x~3.0之间的版本称之为经典蓝牙,4.x开始的蓝牙称之为低功耗蓝牙,也就是蓝牙BLE。即使套接字尚未连接,输入流也会返回,但对该流的操作将抛出IOException异常,直到关联的套接字连接。方式二:通过反射的方式来设置蓝牙可见性,且不会出现弹框,如果蓝牙没有开启,通过此方式并不会直接打开蓝牙。

2023-10-29 09:55:14 394

原创 Android多线程学习:线程池(二)

之所以这样设计是因为线程池天生处于一个并发的环下,如果分开用两个变量进行存储,就必须要通过锁进行线程安全处理,从而保证两个变量的修改具备原子性,但是这种做法对性能影响非常严重,因此将两个变量分别包装在一个变量中,最后的并发操作发生在。第二步,若当前线程池处于运行状态,则向阻塞队列中插入一个任务。的时候的需要加锁,如果线程池正在停止,那么要保证当前线程是中断状态,否则要保证当前线程不是中断状态。第三步,如果队列已经满了,新建一个非核心线程执行该任务,如果新建失败,可能是线程池关闭了,或者线程数量达到了。

2023-10-09 15:12:07 513

原创 Android多线程学习:线程池(一)

demo中的构造代码如下,声明了2个核心进程,最大进程数为4,非核心进程空闲超时时长是3s。阻塞队列使用。

2023-10-09 14:50:55 298

原创 Android多线程学习:多线程同步

线程安全是以牺牲程序运行效率为代价的,因此在注意线程安全的同时,也要注意不要滥用锁和同步方法,尽量只对那些会改变竞争资源的方法进行同步。预防死锁:这是一种较简单和直观的事先预防的方法。但可通过系统所设置的检测机构,及时地检测出死锁的发生,并精确地确定与死锁有关的进程和资源,然后采取适当措施,从系统中将已发生的死锁清除掉。避免死锁:该方法同样是属于事先预防的策略,但它并不须事先采取各种限制措施去破坏产生死锁的的四个必要条件,而是在资源的动态分配过程中,用某种方法去防止系统进入不安全状态,从而避免发生死锁。

2023-10-09 14:33:23 396

原创 Android多线程学习:线程

后台线程又称为守护线程(Daemon Thread),JVM的垃圾回收线程就是典型的后台线程。:CPU调度的基本单位,线程之间共享所在进程的资源,包括共享内存,公有数据,全局变量等。:系统资源分配的基本单位,进程之间相互独立,不能直接访问其他进程的地址空间。:如果就绪状态的线程获得了CPU,那么程序就处于运行状态。执行结果:报异常,提示中断,取消线程阻塞,执行休眠后操作。:线程执行体执行结束,以及抛出一个未捕获的。关键字之后,该线程就处于新建状态,方法之后,该线程就处于就绪状态,运行结果2,执行时放开。

2023-10-08 18:06:40 425

原创 Android - kts文件配置应用签名

升级最新的AndroidStudio后,gradle配置文件从Groovy 迁移到 KTS,这里把自己配置应用签名遇到的问题及注意事项分享下。Google官方说明地址。

2023-09-26 16:11:34 2994

原创 Android - Handler使用问题总结

调用后直接终止Looper,不在处理任何Message,所有尝试把Message放进消息队列的操作都会失败,比如Handler.sendMessage()会返回 false,但是存在不安全性,因为有可能有Message还在消息队列中没来的及处理就终止Looper了。从打印可以看到,loop()后的log没有打印,因为现在Looper处于一直循环处理消息的状态,这就意味着这个Looper一直处于一个阻塞状态。的时候,默认使用的是当前线程的Looper,就是系统为我们创建好的。给移除掉了,所以不会执行。

2023-09-25 11:12:09 518

原创 Android - Monkey 测试应用出现Crash报错IllegalStateException

在逻辑中先判断当前是否处于Monkey测试,如果处于Monkey,不执行Lottie动画会crash的方法。平时使用Lottie动画都是正常的,没出过这个crash问题,看下的报错信息,代码总文件夹也设置了。目前没有找到正面解决的方法,如有更好的方法可以评论区留言。

2023-09-22 18:29:20 698

原创 Compose学习 - 环境配置及compose、kotlin插件、gradle、AndroidStudio版本对应关系

最近学习Compose,一开始学习的Compose版本是1.1.1,学习的过程中发现,这个方法只有在1.2.0以后版本才支持。想着既然要升级,直接用最新的好了。后面按照官网建议,下载了最新的AndroidStudio,我目前下载的最新的是giraffe版本。

2023-08-31 10:57:37 3615 1

原创 Compose学习 - remember、mutableStateOf的使用

运行应用,旋转屏幕,更改为深色模式,或者终止进程。是两个接口,它们具有特定的值,每当该值发生变化时,它们就会触发界面更新(重组)。当发生任何配置更改或者进程终止时,也会出现这种情况。因此在使用的时候可直接用,不需要用。也就是说,这个变量不会触发界面的刷新。在显示界面中,数据变动,界面刷新是非常常见的操作,所以使用。函数从头调用一遍,每次调用时候,走到第一行语句,就又赋值为0,所以看起来就是没有改变,依然是0。在这种情况下,假如还想记住上一次变量值,就要用到。显示数字是不会变化的,原因是。

2023-08-31 09:40:54 663

原创 行为型(十一) - 中介模式

借鉴下参考链接的例子航空管制,为了让飞机在飞行的时候互不干扰,每架飞机都需要知道其他飞机的实时位置,这就需要时刻跟其他飞机通信。很多架飞机相互通信就会变得很复杂,也容易出事,这时候我们需要增加一个中介飞行控制中心,获取每个飞机的实时位置并规划飞机航行路线。:中介模式定义了一个单独的(中介)对象,来封装一组对象之间的交互。将这组对象之间的交互委派给与中介对象交互,来避免对象之间的直接交互。

2023-08-23 11:19:43 81

原创 行为型(十) - 解释器模式

举个常见的面试题,输入这样一个字符串“6 3 5 7 - + * ”,中间空格隔开。前面是运算的数,后面是运算符。先取前两个数6 3,再取一个运算符-,6-3=3,然后用结果继续和后面的数进行计算3+5=8,8*7=56。:解释器模式为某个语言定义它的语法(或者叫文法)表示,并定义一个解释器用来处理这个语法。实际应用中较少用到的行为模式。

2023-08-23 11:18:56 71

原创 行为型(九) - 命令模式

请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。这里借鉴菜鸟教程的例子,一个经纪人处理股票买卖订单的过程。3、经纪人,可处理股票订单。1、股票抽象类及实现类。

2023-08-23 11:18:33 90

原创 行为型(八) - 备忘录模式

也叫快照(Snapshot)模式,在不违背封装原则的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便之后恢复对象为先前的状态。通俗点就是用于保存某个对象的状态,以便在适当的时候恢复对象。简单的应用比如:游戏存档、浏览器中的后退、word中的撤销。操作过程状态,该数据一旦创建不能留修改入口。

2023-08-23 11:18:07 66

原创 行为型(七) - 访问者模式

改变元素类的执行算法,来控制对数据结构的操作方式,也就是执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。总结:通过上面的例子,在梳理下概念,我们使用了一个访问者类,改变元素类的执行算法。这个访问类就是例子中的。:我们使用了一个访问者类,改变元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。:把业务操作跟具体的数据结构解耦。我们实现对不同文件的不同操作。

2023-08-23 11:17:43 75

原创 行为型(六) - 状态模式

判断当前状态,切换为下一个状态。为了避免过多状态及操作代码耦合,将各个状态都单独拆出来,在状态类中加入状态流转逻辑,把执行操作抽离到。总结:个人理解,使用场景就是包含有多种状态,且状态间可通过一些操作进行转换。正常硬代码实现,就是。: 一个对象的行为由它的状态决定,而且它必须在运行时根据自身状态改变它的行为。:类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。2、状态实现类,这里代码只贴了两个状态,其他都类似。

2023-08-23 11:17:06 48

原创 行为型(五) - 迭代器模式

总结:对于类似数组和链表这样的数据结构,遍历方式比较简单,在原来的类中实现也可以。如果将这部分遍历的逻辑写到容器类中,也会导致容器类代码的复杂性,所以统一将遍历操作拆分到迭代器类中。通俗的讲:迭代器模式就是提供一种遍历的方法,这种方法有两个特点:一是按你想要的方式访问到你想访问的元素,二是不暴露底层是什么存的。大部分编程语言都提供了遍历容器的迭代器类,我们在平时开发中,直接拿来用即可,几乎不大可能从零编写一个迭代器。:迭代器模式将集合对象的遍历操作从集合类中拆分出来,放到迭代器类中,让两者的职责更加单一。

2023-08-23 11:16:26 94

原创 行为型(四) - 责任链模式

将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。1、在上面代码的基础上加一个QuestionHandlerChain类来保存所有处理器。具体的实现方式有两种,用链表存储处理器和用数组存储处理器。

2023-08-22 09:37:36 47

原创 行为型(三) - 策略模式

策略模式和工厂模式结构很像。工厂模式是解耦对象的创建和使用,策略模式解耦的是策略的定义、创建、使用这三部分。这里以三国时期诸葛亮给刘备三个锦囊的故事为例子,锦囊相当于解决策略。:定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。

2023-08-22 09:37:06 44

原创 行为型(二) - 模板模式

模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。这里举一个考试出试卷的例子,假设一个科目的试卷题型相对固定,选择、简答、论述,每次出题都是这几种类型。而这个科目每个月都要出一张试卷进行考试。1、模板接口,producePaper设计为final,避免子类重写。

2023-08-22 09:35:45 113

原创 行为型(一) - 观察者模式

在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知。这里举个电视剧订阅的例子,比如琅琊榜,我们订阅以后,每集更新都会通知到所有的订阅者。

2023-08-22 09:35:03 60

原创 结构型(七) - 外观模式

现在年轻人比较喜欢智能家居,很多家电都可以用手机智能控制,比如:家里的灯可以语音或者手机软件上进行开关,智能窗帘、电视等都可以通过手机一键开启关闭。但是每次操作都需要一个一个进行,回家后对这些家电的操作方式基本一致,因此,我们定义一个“回家模式”外观类。:外观模式不符合“开闭模式”,当子系统类增加或者减少的时候,都需要修改外观类中的方法。:外观模式是迪米特法则的践行者,遵循着让客户端知道最少的原则,实现客户端和子系统类的解耦。2、外观模式 - 定义个“回家模式”,回家以后把灯打开,窗帘关上,电视打开。

2023-08-22 09:34:39 62

原创 结构型(六) - 组合模式

组合结构不常用,需要部分与整体的层次关系为树形结构,并且部分与整体的对象是能让客户端能统一对待、不需区分的对象,例如:文件管理系统,在遍历查找的时候,文件和文件夹对我们来说不做区分,可以做到逻辑统一。这里借鉴参考文章公司和职员的例子,公司的组织结构包含部门和员工两种数据类型。其中,部门又可以包含子部门和员工。然后通过构建树形结构来遍历计算公司总的工资支出成本。:将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。1、定义公司及员工的父类。

2023-08-22 09:34:12 78

原创 结构型(五) - 适配器模式

正常插排提供的电压是220V,但是我们的电子设备可能只需要5V电压,所以厂商会提供一个充电器,这个充电器就是适配的作用。如果接口不多,我个人觉得对象适配器更好些,因为在调用的时候会把被适配器类传递进去,这样看代码的时候就能知道是对哪个类进行了适配,以后修改的时候也会注意。:这个模式就是用来做适配的,它将不兼容的接口转换为可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作。:适配器模式是一种事后的补救策略,我们在设计初期,就应该尽量规避掉接口不兼容的问题。的接口,比起对象适配器的实现方式,

2023-08-22 09:33:52 71

原创 结构型(四) - 装饰器模式

系统中有一个通知功能,通知分为紧急、重要、一般等几个等级,以前发通知就发一段文字。5、加入图片和动画的装饰类,首先实现一个NotificationDecorator类,来统一实现setNotice、getNotice等方法,这样后面子类直接调用就行。8、调用实现,在原来文字通知的基础上加上一个图片,后面是叠加一个动画装饰器,既显示文字又显示图片还是显示动画,即装饰器可相互嵌套,为原始功能增加多个功能。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

2023-08-22 09:33:13 58

原创 结构型(三) - 享元模式

所有玩家都可以选择这个武器,由于这个武器一旦上线一般不会改动,它内部的杀伤力等配置都是固定的,所以没必要为每一个玩家新建一个武器对象,这个武器就可以设置为全局唯一享元对象。但是,对于字符串来说,我们没法事先知道要共享哪些字符串常量,所以没办法事先创建好,只能在某个字符串常量第一次被用到的时候,存储到常量池中,当之后再用到的时候,直接引用常量池中已经存在的即可,就不需要再重新创建了。:我们在需要创建大量(例如10^5)的相似的对象时,使用享元模式,把不可变的对象单独抽出来,进行共享可以减少内存消耗。

2023-08-22 09:32:39 93

原创 Android - ViewBinding学习使用

枯燥又没什么意义,因此针对这个问题也出了很多开源库来解决,例如:Butter Knife(黄油刀)。插件,当时用的时候真是感觉像发现了新大陆一样,非常好用。功能之后,Android Studio会自动为我们所编写的每一个布局文件都生成一个对应的Binding类。之间进行绑定,并不算是非常方便。但是,当你的gradle升级到新版本的时候,会显示下面的提示。标签引入的布局在某些情况下可以减少一层布局的嵌套,而更少的布局嵌套通常就意味着更高的效率。进行重命名处理,而且经常会引用错误的布局文件,导致运行崩溃。

2023-08-22 09:31:28 1229

原创 结构型(二) - 桥接模式

这里用手机和处理器的关系来举个例子,手机牌子有:华为、小米、OPPO等,处理器有:麒麟、骁龙、天玑等。两者的变化维度是相对独立的,各自进行演进,但是不同的手机品牌和不同的处理器可以组合形成不同的产品。因此,我们用桥接的方式把他们连接起来。另一种理解方式:一个类存在两个(或多个)独立变化的维度,我们通过组合的方式,让这两个(或多个)维度可以独立进行扩展。:是用于把抽象化与实现化解耦,使得二者可以独立变化。它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。1、处理器接口及实现。

2023-08-21 10:00:44 430

原创 结构型(一) - 代理模式

6、如果我们要访问国外的网站Youtube,Facebook等,直接访问是不行的,我们就需要加一个vpn,登录vpn后可正常访问。总结:个人理解,vpn这里相当于一个网站代理,我们把要访问的网站给代理类,代理类会处理vpn登录等判断并帮我们访问我们需要的网站。:代理模式最常用的一个应用场景就是,在业务系统中开发一些非功能性需求,比如:监控、统计、鉴权、限流、事务、幂等、日志。动态代理就是我们不事先为每个原始类编写代理类,而是在运行的时候,动态地创建原始类对应的代理类,然后在系统中用代理类替换掉原始类。

2023-08-21 09:59:13 444

原创 创建型(四) - 原型模式

浅拷贝:就是复制了一份肯德基套餐A,但是里面包含的可乐和汉堡还是原来的那一份,如果咬一口汉堡,那么原来的那个就缺一块。总结:从结果看到,说明克隆后的对象和原始的指向的是同一个cola对象,改名字后都变了,但是基本类型数据是没有改变的。总结:这个方式就是把克隆对象中引用的对象也进行浅克隆,但是如果出现嵌套多层的时候,每个引用对象都得实现克隆,太麻烦。深拷贝:也是复制了一份肯德基套餐A,但是里面的可乐和汉堡是新的对象,如果咬一口汉堡,那么原来的那个还是完好无损的。原型模式有两种实现方法,深拷贝和浅拷贝。

2023-08-21 09:57:22 754

原创 创建型(三) - 建造者模式

代码是创建一杯奶茶,奶茶名字是必须的,不然不知道做什么,然后两个可选字段,是否加珍珠和椰果。后面的例子就会报错,因为没有设置名称,就和你去奶茶店给人家说:要一杯奶茶,加珍珠和椰果。:也叫构建者模式,或生成器模式,指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示。:当构造器的参数过多,而且这些参数有些是可选的参数,参数间有相互依赖关系等需求时,可以考虑使用建造者模式。建造者模式是用来创建同一种类型的复杂对象,通过设置不同的可选参数,“定制化”地创建不同的对象。

2023-08-21 09:54:59 447 1

原创 创建型(二) - 单例模式

指令重排问题:当线程A执行到9行的时候,线程B执行到6行,CPU在进行对象创建的时候,内部会在保证不影响最终结果的前提下对指令进行重新排序(不影响最终结果只是针对单线程)。总结:在类加载的时候就对实例进行初始化,没有线程安全问题;总结:上面是线程安全的懒汉模式,在第一次使用的时候才进行初始化,达到了懒加载的效果;此时线程B执行到第6行,发现mInstance不为空,但是对象并没有初始化完成,会出现问题,但是概率较低。:在内存里只有一个实例,减少了内存的开销,避免一个全局使用的类频繁地创建与销毁。

2023-08-21 09:53:07 543

原创 创建型(一) - 简单工厂模式、工厂方法模式和抽象工厂模式

本文使用了王争老师设计模式课程中的例子,写的很清晰,而且中间穿插了代码优化。由于设计模式就是解决问题的一种思路,所以每个设计模式会从问题出发,这样比较好理解设计模式出现的意义。

2023-08-21 09:49:45 1234

原创 设计模式原则及分类

此时如果上层直接依赖底层实体工具,以后新添加一个出行工具就要动上层依赖方代码,此时我们可以给所有下层的交通工具抽象出一个接口vehicl,上层依赖vehicl接口,这样底层代码扩展不会影响上层代码功能。为了使程序的扩展性好,易于维护和升级,在扩展的时候,尽量不要修改原代码,而是要了扩展原代码,比如接口实现。策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

2023-08-21 09:44:54 287

原创 Java中抽象类和接口区别

定义了default的方法可以不被实现子类所实现,但只能被实现子类的对象调用;如果子类实现了多个接口,并且这些接口包含一样的默认方法,则子类必须重写默认方法;接口可以包含变量、方法,变量被隐士指定为public static final,方法被隐士指定为public abstract(接口中可以定义静态方法、default方法,枚举类型,接口中还可以定义接口(嵌套)。抽象类可以包含变量和方法。包含抽象方法的一定是抽象类,但是抽象类不一定含有抽象方法;类实现接口的时候,必须实现接口中声明的所有方法;

2023-08-21 09:38:58 60

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除