
Android
文章平均质量分 81
记录Android开发相关的内容和问题等等。
川峰
8年+Android相关工作经验。专注于移动开发领域。
展开
-
Jetpack Compose 性能优化的几条建议
加了它之后,在 Layout Inspector 中就可以看到重组次数为0,跳过重组的次数有很多(本该重组的次数)。,我们在 Layout Inspector 中观察列表快速滑动的时候,会发现列表出现红色闪烁,这说明发生了重组。我们可以使用三方的图片加载库,如coil,因为图片加载库一般会缓存,同一张图片不会重复加载第二次,还可以根据尺寸压缩等。部分,详细的介绍了稳定类型需要满足的准则,以及什么样的类型是稳定类型或者不稳定类型。,可以优化列表的加载性能,避免多余的重组。不是一个稳定的类型,会导致重组。原创 2024-02-28 08:00:00 · 1812 阅读 · 0 评论 -
Jetpack Compose:实现图片的 Pinch Zoom 从未如此简单
可见 Jetpack Compose 短短几十行代码就实现了传统 View 体系中动辄需要上千行的代码,简直不要太简洁,不仅清晰易懂,而且还易维护。Compose 实现图片的手势操作比传统 View 简便太多了,在传统 View 体系中,如果要对。其实就是放大后的矩形宽度比原始矩形宽度多出的部分,显然此时左右移动的时候,左边和右边不应该超出。限制了偏移量的移动范围,在往左边拖动的时候,不能超过左边的。的回调函数中所做的事情,为了简化,我们可以先将上面。的一半,往右边拖动的时候,同样不能超过右边的。原创 2024-02-27 13:14:12 · 1351 阅读 · 0 评论 -
在 Room 数据库中使用事务处理联表操作
这三块代码的操作不是原子性的,假设第一块代码向数据库插入成功了,但是在跑第二块代码时应用崩溃了,第三块代码就没有执行,从而导致bug。同样的,如果第一块代码和第二块代码执行成功了,但是第三块代码执行失败了,前面部分的操作也不会回滚,从而导致bug。方法中对数据库表的操作,要么全部成功,要么全部失败,即便在中间某个操作应用崩溃了,也不会只执行了一半,即保证事务是原子性的。更多关于 Room 数据库中对象与对象之间的关系定义,请参考。正确的处理方法是使用 Room 数据库中的。注解,在其中执行相关的表操作。原创 2024-02-27 13:11:08 · 801 阅读 · 0 评论 -
Jetpack Compose 状态管理的三个误区
但是作为开发者应该有这样的意识,一旦用户有这样的需求,我们就可以立即修改代码来达到需求。如果应用回到后台,随时有可能因为内存不足而被系统杀死,这时用户从最近应用程序列表中返回时,会发现应用界面从头开始,上次看到的状态丢失。当中,然后用户继续浏览,然后用户又切到其他应用,此时当前应用因为某种原因进程被杀死重启(如内存不足),那么这个时候 object。值增加之后,回到后台去做其他事情,此时应用因为内存不足被系统杀死,用户再次返回应用,应用会重启,用户看到的将会是初始值 0。(View system),以及。原创 2024-02-27 13:00:03 · 1374 阅读 · 1 评论 -
Jetpack Compose 中三个好用你却不知道的 Modifier 修饰符
【代码】Jetpack Compose Text 跑马灯效果。原创 2024-02-26 11:45:17 · 661 阅读 · 0 评论 -
Kotlin 协程中容易让人忽视的 Cancellation 陷阱
启动的协程作用域没有被真正取消,这与我们的预期不符,当用户按下返回键关闭页面时,我们期望的是取消协程中正在后台执行的上传任务,否则这容易导致内存泄漏。,该异常不会取消它的父协程,这个异常通常会被忽略静默处理,但是假如你捕获了该异常,那么父协程就不会感知到任何取消通知,也就不会取消协程。注意,检测协程是否被已被取消,最好是在循环中,或者如果没有循环逻辑则每隔一段代码调用一次检测,所以上面读取文件的代码最好不要使用。这个示例的问题在于,协程的取消可以是在任何时机,不一定在某个方法当中,例如在。原创 2024-02-26 08:21:55 · 1365 阅读 · 0 评论 -
使用 Koltin 集合时容易产生的 bug 注意事项
可以看到这个问题的解决并非难事,非常简单,困难的是如何发现这种问题,如果没有并发安全的意识,可能只能对着应用抛出的异常日志发呆而无从下手。所以,如果你没有意识到集合类可能在多线程下导致的并发安全问题,一旦产生这样的bug或异常,就会很棘手,很难发现问题的原因。的消息了,因为被线程 1 删除了一个,消息列表不够 4 个了,这种情况下,你的应用可能会得到某种类似于。类的相关方法,那么不会有任何问题,但是假如你在多个线程中调用这个类,比如在线程池中跑,那就不一定了。类那样,每次操作都会产生一个新的不可变。原创 2024-02-27 07:30:00 · 603 阅读 · 0 评论 -
3 个Android Kotlin 小技巧教你做人:好的编码习惯胜过好的编码技术
在没有使用 Kotlin 之前,使用Java的时候,或许你有封装过一些工具类来做类似的事情,但是下面我们看一下如何通过 Kotlin 的属性代理的方式来简化类似这种读写数据的逻辑。中读取的,这样将读写的逻辑隐藏在了背后,开发者只需要读,但不需要关心具体是怎么读的,能够更好的把精力放在纯业务问题上。),但这不并妨碍本文以此作为示例来演示问题所在,如果你有其他的比较复杂的读写逻辑想要简化,其实处理方式是类似的。现在的问题是,如果这个接口的调用者在不看注释的情况下,如何知道这个方法的返回值代表的是一个。原创 2024-02-26 07:30:00 · 1205 阅读 · 0 评论 -
《深入理解 Android ART 虚拟机》笔记
另外,ART 还借助一种称之为 Lock Hierarchies 的方法来解决线程同步时经常出现的因为使用锁的顺序不一样导致死锁的问题(即线程应该按相同的顺序抢占互斥锁,比如先锁住互斥锁A,接着再锁住互斥锁B,否则极易出现死锁的情况)。很多人以为 Java 字节码编译成机器码后就能和那些 C/C++ 编译得到的机器码一样无所羁绊地直接在OS上运行了,殊不知在Java字节码编译为机器码的过程中,虚拟机会添加一些必要和特殊的指令,使得得到的机器码在运行过程中实际上离不开虚拟机的管控。笔者称这种双字节元素为。原创 2023-12-13 16:42:53 · 2568 阅读 · 0 评论 -
【C++】线程安全加锁操作 Mutex::AutoLock 介绍
Android 中 Zygote 进程启动以后,负责 fork 应用进程,在 fork 出应用进程以后,会为应用进程启动 Binder 机制,具体在中:在 中,主要调用了 ,这个函数主要返回了一个 单例,并且这里使用了 互斥锁。是互斥类,用于多线程访问同一个资源的时候,保证一次只有一个线程能访问该资源。在《Windows核心编程》一书中,对于这种互斥访问有一个很形象的比喻:想象你在飞机上如厕,这时卫生间的信息牌上显示“有人”,你必须等里面的人出来后才可进去。这就是互斥的含义。下面来看的实现方式,它原创 2023-11-06 03:18:22 · 266 阅读 · 0 评论 -
使用 Messenger 跨进程通信
使用 Messenger 跨进程通信的范例代码。原创 2023-09-16 22:23:14 · 474 阅读 · 0 评论 -
Android 匿名共享内存的使用
Android 匿名共享内存工具 MemoryFile 的使用。原创 2023-09-15 07:15:00 · 819 阅读 · 0 评论 -
AIDL+MemoryFile匿名共享内存实现跨进程大文件传输
使用AIDL+匿名共享内存实现跨进程双向通信和大文件传输。原创 2023-09-15 07:00:00 · 2358 阅读 · 0 评论 -
Android AES加密解密工具类
一个Android AES加密解密工具类 一个Android AES加密解密工具类 一个Android AES加密解密工具类 一个Android AES加密解密工具类 一个Android AES加密解密工具类 一个Android AES加密解密工具类 一个Android AES加密解密工具类 一个Android AES加密解密工具类 一个Android AES加密解密工具类 一个Android AES加密解密工具类 一个Android AES加密解密工具类 一个Android AES加密解密工具类 一个An原创 2023-03-11 08:00:00 · 1570 阅读 · 0 评论 -
Gradle 从 Groovy 到 KTS 迁移
本文主要记录Groovy版本和kotlin版本的Gradle 相关设置。以便备忘或以后迁移参考。原创 2023-02-07 08:00:00 · 1677 阅读 · 0 评论 -
Jetpack架构组件库:DataStore
Jetpack DataStore 是一种经过改进的新数据存储解决方案,旨在取代 SharedPreferences。DataStore 基于 Kotlin 协程和 Flow 构建而成,提供以下两种不同的实现:Preferences DataStore 用于键值对存储。数据以异步、一致和事务性的方式存储,有助于避免 SharedPreferences 的一些缺点。此实现不需要预定义的架构,也不确保类型安全。Proto DataStore 用于存储类型化对象,数据作为自定义数据类型的实例进行存储。此实现原创 2023-01-29 08:00:00 · 64948 阅读 · 0 评论 -
Jetpack架构组件库:WorkManager
工作使用Worker类定义。Worker类的doWork()方法在提供的后台线程上异步运行。如需为创建一些要运行的工作,请继承Worker类并重写doWork()方法。从doWork()返回的Result会通知服务工作是否成功,以及工作失败时是否应重试工作。:工作成功完成。:工作失败。:工作失败,应根据其重试政策在其他时间尝试。默认情况下,当您的应用启动时,WorkManager 使用适合大多数应用的合理选项自动进行配置。原创 2023-01-28 10:59:56 · 1325 阅读 · 2 评论 -
Jetpack架构组件库:Lifecycle、LiveData、ViewModel
LifecycleOwner 是单一方法接口,表示类具有 Lifecycle。它具有一种方法(即 getLifecycle()),该方法必须由类实现。 此接口从各个类(如 Fragment 和 AppCompatActivity)抽象化 Lifecycle 的所有权,并允许编写与这些类搭配使用的组件。任何自定义应用类均可实现 LifecycleOwner 接口。实现 DefaultLifecycleObserver 的组件可与实现 LifecycleOwner 的组件完美配合,因为所有者可以提供生命周期原创 2023-01-27 08:00:00 · 1758 阅读 · 0 评论 -
Jetpack架构组件库:Hilt
为了执行字段注入,Hilt需要知道如何从相应组件提供必要依赖项的实例。“绑定”包含将某个类型的实例作为依赖项提供所需的信息。向Hilt提供绑定信息的一种方法是构造函数注入。在某个类的构造函数中使用@Inject注解,以告知Hilt如何提供该类的实例:在一个类的代码中,带有注解的构造函数的参数即是该类的依赖项。在本例中,是的一个依赖项。因此,Hilt还必须知道如何提供的实例。注意:在构建时,Hilt会为Android类生成Dagger组件。然后,Dagger。原创 2023-01-26 09:30:00 · 2387 阅读 · 0 评论 -
Gradle Receipes (AGP-7.3) & AGP 使用指南
本文所有代码是基于 https://github.com/android/gradle-recipes agp-7.3分支版本的官方 sample。由于缺乏清晰易懂的说明文档 ,有些sample代码即便能够跑通,但在细节方便仍然不是很容易让人理解。从 AGP 7.0 开始,AGP的API相较AGP 7.0 以前的变化较大,且迭代更新比较频繁,目前官方最新已迭代至8.0,请注意对照你所使用的AGP版本。但是据官方的说法是,另外Gradle插件和Android Studio的版本之间存在着兼容要求,请参考这里原创 2023-02-08 08:00:00 · 1794 阅读 · 0 评论 -
Jetpack架构组件库:Room
默认表名与类名相同,如需显示指定表名,使用如需显示指定表中的列名,使用每个 Room 实体都必须定义一个主键,用于唯一标识相应数据库表中的每一行。执行此操作的最直接方式是使用@Entity data class User(@PrimaryKey // 主键 val id : Int , val name : String , val age : Int)如需设置主键自动生成,使用。原创 2023-01-26 06:18:57 · 2029 阅读 · 0 评论 -
Android 12 行为变更:适配以Android 12为目标的应用
Android 12目前还是开发者预览版,预计到8月份会出正式版,但是官网已经给出了关于以Android 12为目标的应用适配应该注意的事项。包含 intent 过滤器的应用组件必须声明 exported 属性以 Android 12 为目标平台的应用,且包含使用 intent 过滤器的 activity、服务或广播接收器,必须为这些应用组件显式声明 android:exported 属性。如果 activity、服务或广播接收器使用 intent 过滤器,并且未显式声明 android:export原创 2021-05-24 22:12:29 · 6078 阅读 · 2 评论 -
Android 实现全局浮动弹窗
全局浮动小窗口,类似于微信的语音通话全局小窗口,还有一些手机的桌面的全局操作按钮等,算是比较常用,简单记录一下。实现原理:在Application中,getSystemService(Context.WINDOW_SERVICE) 获取WindowManager,然后通过WindowManager添加View, 手势滑动时实时更新该window的LayoutParams的x | y 坐标。核心代码:Application中创建window:public class App extends Appl原创 2021-04-23 16:34:39 · 3104 阅读 · 2 评论 -
Android Lifecycle生命周期组件探索
最近了解到一个开源库,uber的 AutoDispose,由于不经常使用RxJava,竟然不知道还有这么个东西。。它的主要作用就是在Activity或View销毁不可用的时候自动取消RxJava的订阅,也就是常用的Disposable切断管道流, 取消订阅,避免内存泄漏。AutoDispose将之前的Disposable.dispose()操作做了封装,可以自动处理。它的使用就不去详细探索了,搜索一下就有一堆,这里主要探究一下AutoDispose的实现原理的关键技术点,既然它能在AC销毁的时候自动取消,原创 2021-04-14 23:37:03 · 1399 阅读 · 2 评论 -
EventBus源码学习
在进入主题之前,我们先保持着这样几个疑问,EventBus的使用三要素里,我们为什么要去定义事件方法,并且用到了@subscribe()注解? EventBus.getDefault().register(Object)这行代码到底干了什么?发送事件的时候又做了哪些操作?为什么要在onDestory()做解除绑定的操作…等等(一) 注册: EventBus.getDefault().regist...转载 2019-06-11 19:39:36 · 207 阅读 · 0 评论 -
EventBus使用详解
EventBus是一个基于发布者/订阅者模式的事件总线框架。发布者/订阅者模式,也就是观察者模式(定义了对象之间的一种一对多的依赖关系,当一个对象状态发生改变时,它的所有依赖者都会收到通知并自动更新)。在EventBus中,当发布者发布事件时,所有订阅该事件的事件处理方法将被调用。EventBus的优点:解耦和简化Activities, Fragments等组件以及后台线程之间的通信,分...原创 2019-06-03 20:41:17 · 22615 阅读 · 5 评论 -
Android应用被后台杀死后如何重新走闪屏逻辑
Android应用运行在后台的时候,经常被系统的LowMemoryKiller杀掉,当用户再次点击icon或者从最近的任务列表启动的时候,进程会被重建,并且恢复被杀之前的现场。什么意思呢?假如APP在被杀之前的Activity堆栈是这样的,A<B<C,C位于最上层APP被后台杀死后,APP端进程被销毁了,也就不存在什么Activity了,也就没有什么Activity堆栈,...转载 2019-05-07 20:39:07 · 1569 阅读 · 0 评论 -
Okio源码学习分析
在之前的文章Okio—— 更加高效易用的IO库中参考官方的demo简单学习了一下Okio的使用方法,这篇就来简要分析学习一下Okio的源码实现。Okio源码中主要有这么几个重要的东西:Source和SinkSegmentBufferByteStringTimeout下面依次来看一下这几个东东:Source & Sink这两个是Okio中最基本的两个接口,分别对应jav...原创 2019-04-18 10:31:16 · 1897 阅读 · 2 评论 -
Okio—— 更加高效易用的IO库
在OkHttp的源码中经常能看到Okio的身影,所以单独拿出来分析一下,作为作为OkHttp的低层IO库,Okio确实比传统的java输入输出流读写更加方便高效。原创 2019-04-08 20:09:02 · 22928 阅读 · 7 评论 -
Android android:launchMode=“singleInstance” 页面跳转黑屏
将Activity的启动模式设置为singleInstance,即android:launchMode=“singleInstance”当应用跳转到启动模式设置为singleInstance的Activity页面时,出现一段黑屏修改方式如下步骤一、在AndroidManifest.xml中设置Activity主题 android:theme="@style/Theme.TitleBar"&...转载 2019-04-03 15:16:08 · 1417 阅读 · 0 评论 -
Android锁屏下弹窗的尝试
首先,可以确定的一点是锁屏下弹出页面必须用Activity实现,用WindowManager和Dialog均不行,然后有个注意的地方就是某些手机默认是不允许应用在锁屏下弹出界面的,比如小米的MIUI和魅族的Flyme, 需要在设置中打开一项权限才可以:并且这个权限不能像其他权限一样可以在代码中动态申请,只能用户手动选择允许。在我的手机上这个权限默认是禁止的,即便选择询问,有时也是不能弹出询问...原创 2019-03-25 21:27:56 · 4301 阅读 · 4 评论 -
OkHttp3错误异常: java.net.ProtocolException: unexpected end of stream 源码分析
之前在项目中调试部分上传附件的接口时遇到unexpected end of stream错误,在项目所使用的网络框架是我基于OkGo封装的一个网络请求库,而OkGo内部则其实是基于OkHttp封装的。网上查阅了一下发现遇到这个问题的人挺多,导致这个异常的原因可能不止一种,本文主要针对我遇到的这种情况下导致这个问题的原因分析,做个记录。首先看一下错误日志:看到这个错误的原因,起初我有点担心可能...原创 2019-03-18 21:06:40 · 42302 阅读 · 11 评论 -
Activity在锁屏时的诡异生命周期
最近突然发现Activity在锁屏时生命周期有点奇怪,在我的手机魅族7.1.1上测试基本是下面的结果:按下电源键锁屏:onPause-----onStop再按下电源键解锁:onRestart-----onStart-----onResume这个结果还是比较准确的,大多数时候都是这样的结果,但是跟其网上他人所描述的情况有所不同,大部分人会出现在锁屏时Activity进行销毁重建(onDestr...原创 2019-03-15 15:22:25 · 2619 阅读 · 1 评论 -
关于Fragment的onResume() 以及可见状态的判断
Fragment中有onResume()和onPause()方法,一般来说这两个方法是跟Activity绑定的,即触发Activity的这两个方法时就会触发Fragment的这两个方法,另外Fragment还有可见与不可见状态,但是Fragment中的onResume()/onPause()和可见/不可见完全是两码事。这里我将这两种情况做了一下分析,以做记录。一、onResume()和onPau...原创 2019-02-14 19:02:21 · 6510 阅读 · 0 评论 -
Android创建/删除桌面快捷方式
创建桌面快捷方式,老的代码就不贴了,网上一大堆,基本是intent设置各种action。从Android 7.1(API 25)开始,Android新增了ShortcutManager,可以对桌面久按应用图标弹出的快捷方式进行管理,但是API 25上仍然可以使用老的方式添加快捷方式,从API 26开始支持通过ShortcutManager添加快捷方式了。为了兼容低版本我们可以使用support提...原创 2019-01-31 16:52:16 · 3571 阅读 · 1 评论 -
IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling
最近在使用RecyclerViewAdapter的时候遇到这个问题,这里总结记录一下,先看一下报错日志:原因是我在Adapter中的item放了一个CheckBox, 并给CheckBox设置了监听,当选中状态改变的时候,在监听回调中直接调用notifyItemChanged就会出现这个问题。代码如下: @Override protected void convert(fina...原创 2019-01-31 16:15:10 · 24365 阅读 · 16 评论 -
根据资源名称动态获取资源id的两种方式
通常情况下我们使用R.xxx的方式引用资源,在某些情况下需要根据资源的name来获取资源的id,查了下资料,目前主要有两种方式,这里总结记录一下:第一种,通过反射来获取例如,根据name获取drawable资源: private int getDrawableId(String drawableName) { try { Field field ...原创 2019-01-31 15:10:36 · 4493 阅读 · 0 评论 -
温故而知新:重新认识Activity的生命周期
原创 2019-01-07 17:02:48 · 879 阅读 · 0 评论 -
Android Sqlite数据库升级时注意事项
在app版本升级时,同时升级了Sqlite数据库的版本号的话,如果需要保留之前的数据,需要在onUpgrade方法中做处理。这里记录一下在onUpgrade处理升级的时候的一些注意事项。先看下常用的SQLiteOpenHelper的方法:public class DatabaseHelper extends SQLiteOpenHelper { public DatabaseHe...原创 2018-08-30 11:23:38 · 3906 阅读 · 0 评论 -
Android FlexboxLayout布局属性详解
FlexboxLayout是Google I/O 大会上开源的一个布局控件,使得 Android 里的布局能像 CSS中的Flexible属性一样能拥有同样强大的功能。FlexboxLayout 可以理解为高级的 LinearLayout ,因为这两个布局都将其子视图按序排列。二者之间的重要差异在于 FlexboxLayout 具有 “换行” 的特性。同时FlexboxLayout还为Recycl...转载 2018-08-29 10:58:01 · 2188 阅读 · 0 评论