自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

hegan2010的博客

默认标题

  • 博客(66)
  • 收藏
  • 关注

翻译 【译】Jetpack Compose 稳定性说明

在讨论稳定性之前,让我们快速回顾一下重组“重组是当输入发生变化时再次调用可组合函数的过程。当函数的输入发生变化时,就会发生这种情况。当 Compose 根据新输入进行重组时,它仅调用可能已更改的函数或 lambda,并跳过其余部分。通过跳过所有未更改参数的函数或 lambda,Compose 可以高效地进行重组。注意那里的关键词——“可能”。当快照状态发生变化时,Compose 将触发重组,并跳过任何未更改的可组合项。重要的是,只有当 Compose 可以确保可组合项的任何参数均未更新时,才会跳过可组合项。

2024-01-02 18:11:21 64

翻译 【译】Jetpack Compose State 指南

什么是 State?“所有的值都可能随着时间的推移而改变”。我介绍了 Jetpack Compose 中管理状态的 9 条准则。如何使用 Jetpack Compose 来管理状态。您需要了解 Jetpack Compose 才能正确运行它。基本思想是单一事实来源和关注点分离。即使在 Compose 之外了解它们也可能很有用。如果您有任何反馈,请告诉我。我想修改一下这篇文章。

2023-12-28 15:07:09 67

原创 Apk 重新打包压缩方案

【代码】Apk 重新打包压缩方案。

2023-09-03 22:11:37 116

翻译 [译] App Startup 使用介绍

官方文档:https://developer.android.com/topic/libraries/app-startup文章目录配置在应用启动时初始化组件实现组件初始化器设置清单条目运行 lint 检查手动初始化组件禁用单个组件的自动初始化禁用所有组件的自动初始化手动调用组件初始化器App Startup 库提供了一种在应用程序启动时初始化组件的简单、高效的方法。库开发人员和应用程序开发人员都可以使用 App Startup 来简化启动顺序并明确设置初始化顺序。App Startup 允许您定义共

2022-05-09 15:07:11 543

转载 [转] 感受异或的神奇

原文:感受异或的神奇 - 金马的Blog什么是异或?Wikipedia的解释:在逻辑学中,逻辑算符异或(exclusive or)是对两个运算元的一种逻辑析取类型,符号为 XOR 或 EOR 或 ⊕(编程语言中常用^)。但与一般的逻辑或不同,异或算符的值为真仅当两个运算元中恰有一个的值为真,而另外一个的值为非真。转化为命题,就是:“两者的值不同。”或“有且仅有一个为真。”定义:1 ⊕ 1 = 00 ⊕ 0 = 01 ⊕ 0 = 10 ⊕ 1 = 1真值表:

2022-04-24 16:54:49 214

转载 [转] Android Miracast投屏入门

原文:https://www.codetd.com/article/12138544哇,打开新世界了。SOS……遇到问题查看资料,中英文该看的都不落下。官配1. AOSP源码:Miracast Sink端源码最早出现在Android 4.2.2上,通过googlesource可以很方便的查看:https://android.googlesource.com/platform/frameworks/av/+/android-4.2.2_r1.2/media/libstagefright/wifi-d

2022-04-11 11:15:52 1754 1

原创 Android 基于 DroidAssist 插件实现无埋点

DroidAssistDroidAssist (源码) 是一个轻量级的 Android 字节码编辑插件,基于 Javassist 对字节码操作,根据 xml 配置处理 class 文件,以达到对 class 文件进行动态修改的效果。和其他 AOP 方案不同,DroidAssist 提供了一种更加轻量,简单易用,无侵入,可配置化的字节码操作方式,你不需要 Java 字节码的相关知识,只需要在 Xml 插件配置中添加简单的 Java 代码即可实现类似 AOP 的功能,同时不需要引入其他额外的依赖。使用方式

2022-02-11 22:33:16 1661

原创 Android Gradle Transform 学习

build.gradle:plugins { id 'java' //id 'groovy' id 'org.jetbrains.kotlin.jvm' version '1.5.31' id 'java-gradle-plugin'}repositories { google() mavenCentral()}java { sourceCompatibility = JavaVersion.VERSION_1_8 targetC

2022-01-06 13:38:46 1480 1

原创 Android 12 SplashScreen 应用启动画面

从 Android 12 开始,在所有应用的冷启动和温启动期间,系统一律会应用 Android 系统的默认启动画面。默认情况下,此系统默认启动画面由应用的启动器图标元素和主题的 windowBackground(如果是单色)构成。注:实际测试发现如果 windowBackground 为一张图片,则会从这种图里提取出单色。假如有一个 SplashActivity 使用了这样的主题(img_splash_new 为一张有图片文字的图): <style name="Theme.SplashTe

2021-12-17 17:30:05 3686

翻译 [译]从 LiveData 迁移到 Kotlin Flow

原文:https://medium.com/androiddevelopers/migrating-from-livedata-to-kotlins-flow-379292f419fbLiveData 是我们在 2017 年需要的东西。观察者模式让我们的生活更轻松,但 RxJava 等选项在当时对于初学者来说太复杂了。 架构组件团队创建了 LiveData:一个非常固执的可观察数据持有者类,专为 Android 设计。 它保持简单以使其易于上手,并且建议将 RxJava 用于更复杂的反应式流案例,利用两者

2021-11-17 16:20:13 204

翻译 [译]关于 Flow 的 shareIn 和 stateIn 操作符的注意事项

原文:https://medium.com/androiddevelopers/things-to-know-about-flows-sharein-and-statein-operators-20e6ccb2bc74Flow.shareIn 和 Flow.stateIn 运算符将冷流转换为热流:它们可以将来自冷上游流的信息多播到多个收集器。 它们通常用于提高性能,在不存在收集器时添加缓冲区,甚至作为缓存机制。注意:冷流是按需创建的,并在被观察时发出数据。 热流始终处于活动状态,无论是否被观察到,都可

2021-11-15 18:39:47 329

翻译 [译]从 Android UI 收集流的更安全方法

原文:https://medium.com/androiddevelopers/a-safer-way-to-collect-flows-from-android-uis-23080b1f8bda在 Android 应用程序中,Kotlin 流通常从 UI 层收集以在屏幕上显示数据更新。但是,您希望收集这些流,以确保在视图转到后台时不会做多余的工作、浪费资源(CPU 和内存)或泄漏数据。在本文中,您将了解 Lifecycle.repeatOnLifecycle, 和 Flow.flowWithLifec

2021-11-15 16:54:03 210

原创 Android 图片处理工具类 ImageUtils

import android.annotation.SuppressLintimport android.graphics.Bitmapimport android.graphics.Bitmap.CompressFormatimport android.graphics.Bitmap.CompressFormat.JPEGimport android.graphics.BitmapFactoryimport android.graphics.Matriximport android.net.U

2021-09-30 16:11:01 431

原创 支持可选择编码可读取大型文本的 TextFileReader

最开始只用 RandomAccessFile 读取每一行,但发现读取太慢了,因为每次都是从磁盘里读取。然后想到了用 MappedByteBuffer 再进行一次内存映射,可以显著提升读取速度。但如果原文件太大了的话,还得进行分块映射处理,要不然会 OOM。最后又发现读取某些文本文件时会出现乱码,原因是 RandomAccessFile 是用 ISO-8859-1 编码,而 ByteBuffer.getChar() 又是用 UTF-16 编码。无奈只能用 Charset.decode(inByteBuf

2021-08-29 12:10:39 441

原创 如何在 Android 进程内通过 Bundle 传递 functional interface 实例

假如我们要在 Bundle 中传递一个实现了 functional interface 的实例,我们可以这样扩展或者定义一个接口:interface Parser<E> : Parcelable where E : Enum<E>, E : LogParser<E> { fun parseLine(line: String): CharSequence}这个接口的泛型参数 E 定义的很巧妙:首先,E : Parser<E>,这是一个自限定类型

2021-08-29 11:37:59 354

翻译 [译] Realm 修改对象模式 - Android SDK

原文:https://docs.mongodb.com/realm/sdk/android/examples/modify-an-object-schema文章目录添加属性删除属性修改属性类型或重命名属性迁移函数以下示例演示了如何在模式中添加、删除和修改属性。首先,进行所需的模式更改。然后,创建相应的迁移函数,将数据从原始模式移动到更新后的模式。使用模式版本的领域0具有Person对象类型:class Person: RealmObject { // Realm schema version 0

2021-07-05 22:22:46 239

翻译 [译] Realm 对象模型和模式 - Android SDK

原文:https://docs.mongodb.com/realm/sdk/android/fundamentals/object-models-and-schemas文章目录Realm 应用程序主键Optionality 可选择性Relationships 关系Indexes 索引Modules 模块Realm 对象RealmProxyRealm 对象限制增量构建总结一个对象模式是一个配置对象,它定义了一个 Realm 对象类型的的字段和关系。Android Realm 应用程序通过使用 Java 或

2021-07-05 22:04:48 343

翻译 [译] 定义 Realm 对象模式 - Android SDK

小费有关模式的概念信息以及有关类型和约束的详细信息,请参阅基础:对象模型和模式。定义一个领域对象要在您的应用程序中定义 Realm 对象,请创建RealmObject的子类 或实现RealmModel。重要的所有 Realm 对象都必须提供一个空的构造函数。扩展RealmObject例子以下代码块显示了一个描述青蛙的 Realm 对象。这个 Frog 类可以存储在 Realm 数据库中,因为它extends是RealmObject类。科特林爪哇import io.realm.Realm

2021-07-05 18:07:19 136

翻译 [译] Kotlin 协程异常处理

原文:https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/topics/exception-handling.md文章目录异常传播协程异常处理器 CoroutineExceptionHandler本节介绍异常处理和在异常时取消。我们已经知道取消的协程会在挂起点抛出 CancellationException 并且它会被协程的机制忽略。这里我们看看如果在取消过程中抛出异常或者同一个协程的多个子协程抛出异常会发生什么。异常传播协程构

2021-06-24 16:02:47 981 1

翻译 [译] 协程中的取消和异常(第 3 部分)- 协程中的异常

原文:https://medium.com/androiddevelopers/exceptions-in-coroutines-ce8da1ec060c文章目录一个协程突然失败了!现在怎么办?????SupervisorJob 来拯救*???? 无论你使用哪种 Job,未捕获的异常都会被抛出*Job 还是 SupervisorJob?????当心测验!谁是我的父母?????了解幕后处理异常????‍????Launch*使用 launch,异常将在发生时立即抛出*Async*当 async 用作根协程时

2021-06-17 18:21:16 194

翻译 [译] 协程中的取消和异常(第 2 部分)- 协程中的取消

在开发中,就像在生活中一样,我们知道避免做多余的工作很重要,因为这会浪费内存和精力。这个原则也适用于协程。您需要确保控制协程的生命周期,并在不再需要时将其取消——这就是结构化并发所代表的含义。继续阅读以了解协程取消的来龙去脉。调用取消启动多个协程时,跟踪它们或单独取消每个协程可能会很痛苦。相反,我们可以依靠取消启动协程的整个 scope,因为这将取消它所有创建的子协程:// assume we have a scope defined for this layer of the appval job

2021-06-17 16:19:35 579

翻译 [译] 协程中的取消和异常(第 1 部分)- 协程:第一件事

原文:https://medium.com/androiddevelopers/coroutines-first-things-first-e6187bf3bb21本系列博客文章深入探讨了协程中的取消和异常。取消对于避免做多余的工作很重要,这会浪费内存和电量;正确的异常处理是良好用户体验的关键。作为本系列其他 3 部分(第 2 部分:取消,第 3 部分:异常,第 4 部分:不应取消的工作的协程和模式)的基础,定义一些核心协程概念非常重要,例如 CoroutineScope, Job 和 Coroutine

2021-06-17 15:08:33 141

翻译 [译] Realm 的使用入门

一、初始化Realm必须先初始化 Realm 库,然后才能在应用程序中使用 Realm。您的应用程序每次运行时都应该仅初始化一次 Realm。要初始化 Realm 库,请将 Android context 提供给 Realm.init() static 函数。您可以提供一个 Activity,Fragment 或 Application context 进行初始化,而在行为上没有差异。您可以在 Application子类 的 onCreate() 方法中初始化 Realm 库,以确保每次应用程序运行时仅

2021-06-16 16:57:45 807

原创 Kotlin 协程三类 Continuation

协程有三层 Continuation 包装,通过代理模式将协程的各层包装组合在一起,每层负责不同的功能。第一层 Continuation 包装是 CoroutineScope.launch() 和 CoroutineScope.async() 方法分别返回的 Job、Deferred,里面封装了协程状态,提供了取消协程的接口,它们所属的类(StandaloneCoroutine、DeferredCoroutine)都是继承自 AbstractCoroutine,而 AbstractCoroutine 实现

2021-06-15 17:41:05 742 1

原创 Kotlin 协程 UML 类图

基于 Kotlin 1.5 版本源码制作:pngjpg

2021-06-14 23:31:44 648 1

原创 Kotlin 协程四类 Dispatcher

Default: 默认情况下,此调度器使用的最大并行数等于 CPU 内核数,但至少为 2。 并行度 X 保证在这个调度器中并行执行的任务不超过 X 个。Main: 不管是否已经在 main 线程中,都将会 Handler.post(block) 执行Main.immediate:如果已经在 main 线程中,将立即执行,否则将会 Handler.post(block) 执行override fun isDispatchNeeded(context: CoroutineContext): Boolean

2021-06-14 22:44:28 716

原创 Kotlin 异步回调转为协程

suspendCoroutine() 方法 和 suspendCancellableCoroutine() 方法都可以将异步转为协程。通过 continuation.resume() 传递结果,continuation.resumeWithException() 传递异常。public suspend inline fun <T> suspendCoroutine(crossinline block: (Continuation<T>) -> Unit): T {

2021-06-14 22:15:52 978

原创 以 Retrofit suspend 方法举例解析 Kotlin 协程原理

前置条件:一个 Retrofit API 接口 VideoApi,其方法是 suspend 方法。interface VideoApi { @GET("https://live.{env}.shopee.{cid}/api/v1/homepage/replay") suspend fun getVideoList( @Path("env") env: String = EnvConstants.NETWORK_ENV, @Path("cid") cid:

2021-06-14 13:33:35 1446 1

翻译 [译] Kotlin Flow 官方 Guide 指南(2021-06-13)翻译

原文链接:https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/topics/flow.mdFlows are coldflow 构建器中的代码在收集流之前不会运行fun simple(): Flow<Int> = flow { println("Flow started") for (i in 1..3) { delay(100) emit(i) }}fun

2021-06-13 17:16:24 434

原创 Kotlin suspend fun 会编译成什么样的代码?

对于这样的 suspend funfun foo(p1 : P1, ..., pn : Pn) : R其编译期生成的代码类似这样: @Nullable public Object foo(P1 p1, ..., Pn pn, @NotNull Continuation continuation) { class LocalContinuationImpl extends kotlin.coroutines.jvm.internal.ContinuationImpl {

2021-06-11 02:17:41 719 1

原创 Kotlin suspend lambda 会编译成什么样的代码?

对于这样的 suspend lambdasuspend (p1 : P1, ..., pn : Pn) -> R其编译期生成的代码如下:public class SuspendLambdaBlock<P1, ..., Pn, R> extends kotlin.coroutines.jvm.internal.SuspendLambda implements FunctionN<P1, ..., Pn, Continuation<? super R>

2021-06-11 01:18:51 530

原创 Kotlin 协程的一些内部实现函数

public suspend inline fun <T> suspendCoroutineUninterceptedOrReturn(crossinline block: (Continuation<T>) -> Any?): T { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } throw NotImplementedError("Implementation of suspend

2021-06-10 19:23:55 209

原创 Kotlin Flow buffer 的使用

public fun <T> Flow<T>.buffer(capacity: Int = BUFFERED, onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND): Flow<T> { ...}缓冲区通过指定容量的通道发射,并在单独的协程中运行收集器。通常,流是顺序的。这意味着所有运算符的代码都在同一个协程中执行。例如,考虑以下使用 onEach 和 collect 运算符的代码:flow

2021-06-07 18:25:59 1393 3

翻译 [译] Kotlin 协程 Flow 官方文档(2021-2-4)翻译

原文:https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/Flow (流)interfaceFlow<outT>(source)异步数据流,它顺序地发出值并正常或异常地完成。流的中间运算符(例如 map, filter, take, zip 等)是应用于一个或多个上游流并返回下游流(可以在其中应用其他运算符)的函数。中间运算符...

2021-02-04 19:58:16 719

原创 OkHttp CookieJar 简单序列化存取

先将将 List<Cookie> 保存到实现了Serializable接口的CookieSerialize类的实例中,然后通过 Java 序列化机制保存到磁盘里,通过 Java 反序列化机制从磁盘里读取出来。一个 host 的 cookie 对应一个序列化文件。需要自己实现 hostStringToFileName 方法,即 host 字符串转化为文件名的规则。import android.app.Application;import android.content.Context;i

2021-01-27 11:38:37 763

原创 RecyclerView支持单选复选的容器实现ButtonGroupRecyclerView

先上图和视频看效果: 屏幕录制2021-01-25 08.51.42 谷歌已经提供了 MaterialButtonToggleGroup, 但是 MaterialButtonToggleGroup 是继承 LinearLayout 的,并且没有增加子View排列的的属性定义,说明只支持线性排列,不能满足需要多行排列的需求。无奈自己仿写了 MaterialButtonToggleGro

2021-01-25 09:40:24 185

转载 [转] 算法数据结构可视化网站

https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

2021-01-10 19:02:36 71

原创 Android byte 数组转 String

不知道什么原因,Android 的 String.java 的好多方法不能使用,抛出这样的异常:throw new UnsupportedOperationException("Use StringFactory instead.");但是呢,StringFactory.java 这个类却又是 @hide,无法直接调用,无奈拷贝出其中的方法,拎出来使用:import java.nio.ByteBuffer;import java.nio.CharBuffer;import java.nio.ch

2020-07-04 01:03:15 4393

原创 Java byte 数组与 int long 互转

public static void intToByteArray(int intValue, byte[] bytes) { bytes[0] = (byte) ((intValue >> 24) & 0xFF); bytes[1] = (byte) ((intValue >> 16) & 0xFF); bytes[2] = (byte) ((intValue >> 8) & 0xFF);...

2020-07-04 00:59:09 362

翻译 [译] Android MediaCodec 官方文档(2020-6-12)翻译

原文:https://developer.android.google.cn/reference/android/media/MediaCodecMediaCodec类可用于访问低级媒体编解码器,即编码器/解码器组件。 它是Android低级多媒体支持基础结构的一部分(通常与 MediaExtractor, MediaSync, MediaMuxer, MediaCrypto, MediaDrm, Image, Surface, 和 AudioTrack 一起使用)。广义而言,编解码..

2020-06-11 16:14:54 953

空空如也

空空如也

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

TA关注的人

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