Android应用
文章平均质量分 82
对于Android知识点的实战实践
不近视的猫
微信公众号:Android猫记
展开
-
如何优雅地使用 when (Switch)
0 -> {}1 -> {}2 -> {}}em…这不是出现了魔术数字了吗?身为有那么一点点追求的程序员👨🏻💻,还得想下,怎么写更合适。这里,我总结了四种方式,并列出相应的场景供大家参考。常量字符串常量数字枚举。...原创 2022-08-19 10:07:58 · 537 阅读 · 0 评论 -
flow 操作符全解析
flow 的执行流程,就生产者和消费者一样,上游产出,下游消费,但是,在默认的情况下,都是生产一个,消费一个,再生产一个,再消费一个,这样进行的。若是生产和消费的速度都很快的话,那倒没有什么问题,但是,若生产速度大于消费速度,就会导致生产效率被强制降低了,因为生产者会一直等到消费者消费完再生产,而这时,我们可以考虑使用 buffer 操作符,可以设置缓存的生成数,就像生产出的商品可以临时存储在仓库一样,并不会阻塞生产者的运行。其实,它算是两个功能的合成,即一个是 buffer 效果,另外一个是合并效果。..原创 2022-08-19 10:07:10 · 737 阅读 · 0 评论 -
我们为什么要用 flow
首先,我们得明确 flow 的适用场景,那便是类似播报机情况,每隔一段时间就播报一段相似的内容。由此,假如我们不使用 flow 的情况下,那我们怎么解决这种问题?List ❎sequence ❎为什么这么快否决它们?因为他们都是阻塞式的,每两个元素间隔的时间,都会阻塞相应的线程,所以就不过多进行说明。而另外两个选项可以实现 flow 的效果,也就是可挂起式运行。回调LiveDataem…回调,也就是观察者模式的代表,确实是可以实现类似的效果,同时,LiveData 也是可以实现相应的效果的。...原创 2022-08-19 10:06:40 · 154 阅读 · 0 评论 -
Flow、SharedFlow、StateFlow 傻傻分不清楚
SharedFlow 就是观察者模式的一个具体实现,可以对观察者进行注册,当被观察者发生改变的时候,就会通知观察者,同时,SharedFlow 还可以存储之前的变化,即当 SharedFlow 变化后,才有观察者注册,这时观察者仍然能够收到之前的变化。其实,这也很容易理解,因为 delay 的时候,该协程都阻塞了,emit 是不会执行到,而当 delay 之后,collect 都执行完成,这时再 emit,自然也不会再执行 collect 里面的代码。关于 Flow 的说明以及使用,可以参考。...原创 2022-08-19 10:03:39 · 1985 阅读 · 3 评论 -
LiveData 与 StateFlow,我该用哪个?
前言LiveData 相信大家都非常熟悉了,但是由于协程与 Flow 的不断发展,之前所使用的技术也正在不断被替代,而 LiveData 的功能与 StateFlow 很相似,所以,很多人都在考虑使用 StateFlow 去替代 LiveData。这里,我们就分析下,LiveData 与 StateFlow 的优缺点,以及我们该如何抉择。LiveData 与 StateFlow 的区别关于 LiveData 与 StateFlow,网上说的最多的区别,其实就是「官方指导文档」中所讲解的这两点,这里我原创 2022-08-05 15:59:12 · 555 阅读 · 0 评论 -
Channel 是什么?
前言Flow 是一种冷流,只有 collect 的时候才会产生数据,而 SharedFlow、StateFlow 虽然是热流,但是,每次 collect 的时候,要么是只能获取最新值,要么把之前存储的值重新都发一遍。有没有一种热流,能更像生产者与消费者,一个专门生产,一个专门消费,答案当然是有的,那便是 Channel。Channel 的使用 GlobalScope.launch { launch { (1..3).forEach原创 2022-08-05 15:58:34 · 423 阅读 · 0 评论 -
channel 进阶
从『Channel 是什么?』中,我们已经清楚 channel 的基本使用以及其参数说明,下面,我们来继续学习它的更深入一点的知识。原创 2022-08-05 15:58:00 · 13957 阅读 · 0 评论 -
BroadcastChannel全解析
对于 channel 而言,更多面向的是一对一的情况,因为一旦receive()后,该数据就被获取了,后续再receive(),也无法拿到之前的数据。但是,类似的,Flow 与 sharedflow 是相对应的,与 channel 相对应的是 BroadcastChannel。...原创 2022-08-05 15:57:11 · 1383 阅读 · 0 评论 -
关于命令模式的误区,你知道了吗
最近项目开发需要用到命令模式,之前没学过,就过去研究了下。但是,理解后发现网上对于命令模式的讲解大多晦涩难懂,并且在选例时容易让人进入一个误区。所以,干脆自己写篇命令模式的讲解,用于自我总结,当然,若能帮上各位同学,那就是赚了。...原创 2022-08-05 15:56:31 · 135 阅读 · 0 评论 -
初始化Library新姿势——App Startup
}println("初始化 ALibrary 成功")}}在这篇文章中,我们尝试使用进行初始化。原创 2022-08-04 10:12:39 · 177 阅读 · 0 评论 -
因为 QUERY_ALL_PACKAGES 权限,我们上不了 Google Play 了
em…今天刚上班就被告知要移除权限,做代码兼容,否则上不了 Google Play 了。if (!}i++) {}}}}当然,并不是这个权限没有了,而是被列为敏感权限,必须有充分的理由说明,才允许上架 GP,否则还是被一票否决。其实说白了就是大路已经被封了,留了条小路,但是小路只能看,不能走。详情可以看看官方说明,假如你们的 App 也需要上架 GP 的话。「使用广泛的软件包(应用)可见性 (QUERY_ALL_PACKAGES) 权限」...原创 2022-08-04 10:10:28 · 5051 阅读 · 5 评论 -
Preferences DataStore全解析
DataStore 是用来取代的一种简易数据存储的解决方案。下面我们来看看如何使用。原创 2022-08-04 10:08:41 · 847 阅读 · 0 评论 -
重拾 Kotlin 协程——异常剖析(4)
前言我们通过上一篇文章知道,在 Android 中,假如线程发生了异常,会导致 App 直接退出,那我们来看看,协程发生异常后,现象会怎么样。示例代码: override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) GlobalScope.launch {原创 2022-08-19 10:08:20 · 465 阅读 · 0 评论 -
重拾线程——子线程异常,为什么 App 会崩溃(3)
前言在 JDK 中,若子线程发生异常崩溃,并不会阻碍主线程的运行。fun main(args: Array<String>){ Thread{ throw NullPointerException("空指针异常") }.start() Thread.sleep(1000) println("主线程执行完成")}运行结果:Exception in thread "Thread-0" java.lang.NullPointerExcept原创 2022-05-07 18:53:30 · 1981 阅读 · 1 评论 -
重拾 Kotlin 协程——获取返回值(3)
前言当我们在同步代码块中执行代码时,获取返回值是一件十分轻松的事情,直接运算结果进行返回即可。但是,协程是一种异步的概念,所以需要一些特别的操作才能获取协程的返回值。经研究,一般使用以下三种:asyncsuspendCoroutinesuspendCancellableCoroutineasync相信大家对 async 都十分理解了,主要流程就是使用 async 去开启协程,然后调用 async 返回的 Deferred 的 await() 方法,即可获取 async 协程运算的结果。具体的原创 2022-05-07 15:20:40 · 3931 阅读 · 0 评论 -
重拾线程——异常处理(1)
关于线程的异常,我们可以先看一个小栗子🌰:fun main(args: Array<String>) { println("-------1---主线程开始执行") try{ Thread{ println("-------2---子线程开始执行") throw Exception("error!!!") println("-------3---子线程异常后执行") }.st原创 2022-04-24 17:19:45 · 1893 阅读 · 0 评论 -
重拾 Kotlin 协程——调度器(1)
基础使用我们若要使用到 Kotlin 协程,首先需要添加依赖:dependencies { implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'}然后通过以下代码就可以启动协程: CoroutineScope(Dispatchers.Main).launch { }这样,就能够在主线程中执行代码了。调度器而这个调度器不仅只有 Dispatchers.Main原创 2022-04-18 03:13:27 · 673 阅读 · 0 评论 -
重拾线程——FutureTask 是如何吃掉异常(2)
前言首先,我们先写个示例代码来运行 FutureTask: val futureTask = FutureTask { println("futureTask 正在执行") throw Exception("我是测试异常") println("futureTask 发生异常了!") return@FutureTask "1" } Thread(futureTask).start()运行结果:futureTask原创 2022-04-24 19:00:42 · 2545 阅读 · 0 评论 -
重拾 Kotlin 协程——结构化并发(2)
取消协程我们都知道,通过以下代码就可以启动一个协程进行运行: CoroutineScope(Dispatchers.IO).launch { }但是,这个跟我们启动线程一样,具有一个很大的问题,就是不可控性,我们知道它什么时候启动,却不知道什么时候销毁,就像我们跳转在一个页面进行数据加载的时候,可以使用协程去加载,但是,我们也希望当该页面销毁的时候,该协程也能够销毁。其实,协程也提供这样的一种方式:class MainActivity : AppCompatActivity() {原创 2022-04-19 17:23:33 · 1411 阅读 · 0 评论 -
都快面试了,还不赶紧复习下HTTP!
什么是HTTP超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。——来自百度百科说白了,其实就是请求-响应协议。请求部分首先,我们先来看个栗子????:在浏览器的地址栏中输入https://blog.csdn.net/m0_46278918,回车。可以看到其请求数据:这些数据已经被浏览器进行排版过了,其实其主要格式为:GET /m0_4原创 2021-03-17 00:12:16 · 100 阅读 · 1 评论 -
自动更改 versionCode
前言在我们每次发布新包的时候,总是需要更改 versionName 和 versionCode,versionName 是展示给用户看的版本名字,所以,每次发布都需要更改,这个可以理解,但是 versionCode 基本都是自增,那有没有什么方式可以让其在发布的时候自增?答案当然是可以的,不然这篇文章就不会发布出去了。正文首先,我们在 gradle.properties 中定义一个 APP_VERSION_CODE :然后在 build.gradle 更改 versionCode 为:ver原创 2022-02-15 16:59:56 · 1792 阅读 · 1 评论 -
sleep()为什么要 try catch
前言当我们在 Java 中使用 sleep() 让线程休眠的时候,总是需要使用 try catch 去包含它: try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }但是,我们却很少在 catch 中执行其它代码,仿佛这个 try catch 是理所当然一样,但其实,存在即合理,不可能无缘无故地多出一个 try原创 2022-02-02 00:32:57 · 2737 阅读 · 0 评论 -
同步屏障与异步消息,从入门到放弃
前言在之前的文章中《面试官:如何提高 Message 的优先级》关于如何提高 Message 的优先级提出个人的理解,有大佬在后面评论所提到的同步屏障+异步消息也能提高 Message 的优先级。首先表示感谢,而外也发觉自己对同步屏障的理解还不够,所以,赶紧研究研究。同步屏障与异步消息说明首先,我们得了解下,什么是同步屏障,它跟异步消息又有什么关系?这里的同步和异步又是什么?这里,我们又要涉及到了 Handler 机制。Android 真是博大精深,而且变化贼快,越学越怀疑自己当年是不是入错行了。原创 2021-04-23 16:45:11 · 333 阅读 · 1 评论 -
给Bugly增加自定义处理异常功能
场景说明相信大家目前已上线的项目都有着捕获崩溃的机制,有些可能是自己写的,有些可能是使用第三方的,例如 Bugly。但是,无论使用什么框架,基本上都是围绕着UncaughtExceptionHandler进行,也就是说,只有应用崩溃了才能上报异常信息。嗯?为什么是应用崩溃了才能上报信息?那是因为大部分框架都是使用这种方式进行异常捕获和上报: Thread.setDefaultUncaughtExceptionHandler(object : Thread.UncaughtExcept原创 2021-04-21 23:22:14 · 1063 阅读 · 0 评论 -
面试官:如何提高Message的优先级
面试经历面试官:看你简历上写着看过 Handler 机制源码,说下如何提高Message的优先级?内心分析中:首先,我们先分析下,这个 Message 是由 Handler 进行发送,然后添加到 MessageQueue 中,Looper 遍历 MessageQueue 获取 Message 出来执行。而 MessageQueue 是通过时间对 Message 进行排序的,若想提高 Message 的优先级,那就是要把 Message 排在 MessageQueue 的前面,这样就会优先执行了。原创 2021-04-20 23:34:31 · 438 阅读 · 4 评论 -
动态代理说明以及模拟 Retrofit 实践
什么是动态代理动态代理的核心为代理模式,代理模式在实践的过程分为静态代理和动态代理。关于代理模式的说明,百度百科是这样说的:代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。使用代码的话语去说明,其实就是定义一个接口,后续的对象 A、B 可以实现该接口并实现其抽象方法 method,但是在访问 A、B 的时候,可以不直接引用 A、B 对象,而是通过接口引用直接调用 method原创 2021-04-20 15:38:20 · 113 阅读 · 0 评论 -
写给还不会在项目中使用RxJava的讲解
首先还是强调下,该文如题所示,若已会使用,那可直接略过,返回上一页了。前言或许会有人疑问,都什么年代了,还不会 RxJava?em…还真有,这并不关乎能力,很大原因在于环境。特别是一些公司技术要求会比较保守,或者技术负责人没有使用这种技术,那刚出来工作的同学就自然而然地不懂怎么使用了。由此,对于一些了解 RxJava,却一直不会在项目开发使用的同学,个人希望能够提供一点帮助,让他们能在项目中逐渐使用。毕竟连上手都不懂,更何谈精通。当然,也有人觉得,网上都这么多优秀的 RxJava 的文章了,为什.原创 2021-04-07 02:04:57 · 256 阅读 · 0 评论 -
制作一个永远不会崩溃的App
最近想给 App 加上一个崩溃后自动重启的功能,便去查找了下资料,毕竟有很长一段时间没弄过。不搜不知道,一搜吓一跳,居然看到这库的实现思路,居然能够让 App 产生异常后,不会崩溃。我当场的表情是这样的: 学完后,表情是这样的:好了,废话不多说,赶紧进正文。该库的 GitHub 地址为:https://github.com/android-notes/Cockroach其有两个版本,两个版本的思路是不一样的,但是能够实现同样的功能——App 不会崩溃。在讲解它的原理之前,我们还是来简原创 2021-03-31 01:38:29 · 1667 阅读 · 4 评论 -
自定义Gradle Plugin+字节码插桩
原本是想写一篇介绍字节码插桩的文章,但无奈的是使用字节码插桩之前需要使用到自定义 Gradle Plugin,似乎暗示着这篇文章并不会短。在了解字节码插桩之前,我们先了解编译插桩。编译插桩是什么相信大家都使用过 ButterKnife,了解过它原理的都知道,它是在编译期间生成相应的 java 文件,到运行时,通过反射机制去获取该生成类,并调用其绑定方法,从而做到控件绑定。(什么?你还没了解过 ButterKnife 原理?赶紧去看看吧——《从手写ButterKnife到掌握注解、Annotatio原创 2021-03-30 17:05:46 · 800 阅读 · 0 评论 -
字节码?别怕,我带你分析分析
使用 java 的人很多,使用 kotlin 的也不少,不过,对于它们编译后的文件,也就是 class 文件,却很多人望而却步,一是它晦涩难懂,二是它对于实际上的业务开发的帮助没那么常用。但是,它并不是没有用处的,只是你不懂而已。开始正文。查看 class 文件首先,我们得先写个 Java 文件:public class Test { public void sayHello(){ System.out.println("Hello"); }}然后使用 ja原创 2021-03-28 02:16:07 · 139 阅读 · 0 评论 -
惊了,还有这种方式手写ButterKnife
ButterKnife的应用如题所示,这篇文章主要讲解手把手教学写个简易版 ButterKnife,所以,还是先看看 ButterKnife 怎么使用,不过大多数人都用过,就不详细介绍,若有需要,请参考:https://github.com/JakeWharton/butterknife虽然有人觉得,在 kotlin 中,使用 KTX 工具或者使用 MVVM,已经很少使用 ButterKnife 了,所以觉得没必要去研究 ButterKnife,但是我们学习并非是为了使用,而是为了清楚其原理及构造原创 2021-03-26 11:34:39 · 204 阅读 · 0 评论 -
你真的了解GC吗?
GC是什么?在计算机科学中,垃圾回收(英语:Garbage Collection,缩写为GC)是指一种自动的存储器管理机制。当某个程序占用的一部分内存空间不再被这个程序访问时,这个程序会借助垃圾回收算法向操作系统归还这部分内存空间。垃圾回收器可以减轻程序员的负担,也减少程序中的错误。——来自维基百科通俗来讲就是,你家里有 100 平方,你会买各种生活用品和家居回来,这些物品都会占用空间。过了一段时间,你会通过各种情况去判断这些物品还需不需要,然后再去进行清除和整理。其中:家里100 平方:原创 2021-03-23 16:42:06 · 3268 阅读 · 10 评论 -
来,带你手写个性能检测工具
性能优化,基本每位 Android 开发都需要考虑这个问题。像LeakCanary、hugo这些都是大家常用的性能检测工具,而这次我要讲的是 BlockCanary,由于这个库很久没更新了,所以可能很多人不认识,但是这并不妨碍我们去理解它的实现原理。OK,开始吹水正文功能介绍首先,先祭出GitHub地址https://github.com/markzhai/AndroidPerformanceMonitor该库的功能主要为检测在主线程运行的操作时长,假如运行超过一定时间(默认为1000毫秒)原创 2021-03-18 02:27:45 · 459 阅读 · 1 评论 -
什么?你连个三色渐变圆角按钮都需要UI切图?
废话不多说,先上效果图:该效果其实由三部分组成:渐变圆角文本渐变关于渐变,估计大家都不会陌生,以往都是使用gradient进行制作:shape_gradient.xml<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/...原创 2020-05-01 23:57:04 · 1090 阅读 · 0 评论 -
Android加载字体包及封装
目录TextView加载字体包封装定义属性值创建自定义TextView获取属性值进行值判断并加载不同的字体包全部源码效果TextView加载字体包在 Android 中,若需要使得某个TextView加载字体包,使用一下方式即可: Typeface typeFace =Typeface.createFromAsset(getAssets(),"fonts/Bold.otf");...原创 2020-04-28 20:50:07 · 1161 阅读 · 0 评论 -
Android网络底层框架设计
简介:很多人在进行网络请求的时候,都是直接请求网络数据,然后每次都自己手动解析数据,判断接口类别,然后再进行下一个步骤,但是其实请求网络数据有很多共性的东西,例如存储请求参数的统一性、后台返回的数据类型统一性、sessionId 过期处理统一性等。(总结《App研发录》第二章(Android 网络底层框架设计))目录:1.网络底层封装2.App 数据缓存设计3.用户登录4.HTT...原创 2020-02-06 16:39:03 · 489 阅读 · 0 评论 -
如何避免项目重构
简介:每个 Android 开发者,几乎都有自身的项目编写规范,好坏在平常的开发时或许难看得出来,一旦涉及到项目维护更新或项目交接开发,是神是鬼,一下便原形毕露。低劣的编写规范会导致项目维护更新成本变大,所交接的人员不愿在此基础上进行操作等。于是,这些项目往往不久后都会进入重构阶段,甚至于放弃目前项目,进行重写。为了避免这些情况的发生,本文总结了几点良好的项目编写规范,可以以此作为参考从而更改...原创 2020-02-06 16:36:53 · 168 阅读 · 0 评论