![](https://img-blog.csdnimg.cn/20201014180756780.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
Android 知识
文章平均质量分 80
Death_Huimie
这个作者很懒,什么都没留下…
展开
-
Handler 在子线程中遇到的问题
Handler 的源码在前面几章分析过,一般也被用于切换线程,刷新UI使用。也被用来做延迟处理事件,一般都是在主线程中使用。根据业务逻辑,开启了子线程,在其中做耗时操作,同时设置了一个超时时间,如果超过了这个时间,则终止操作,进行下一步逻辑。 这是一个很简单的需求,但由于笔误,造成了一个bug,原因在于Handler的延时操作不是在主线程中执行,而是在子线程中,见代码 Handler mHandler; void test(){ HandlerThread ...原创 2021-05-26 09:47:52 · 667 阅读 · 1 评论 -
android 并发同步,常用的锁
android 正常业务逻辑中,一般并发用到的地方不多,不像服务器那样,但并发也是存在的,如果没处理好,会引起线程安全的问题。为了解决这些问题,我们会用些线程安全的数据容器,或者使用并发工具类,再或者自己对方法进行些加锁操作等,这里简单介绍几种常用的方法。synchronized 是关键字,它是作用在JVM上的,我们一般把它用于方法只上,也可以用在方法内,举个栗子public class TestDemo { public synchronized static void test1(...原创 2021-04-27 22:14:18 · 689 阅读 · 3 评论 -
android 网络协议的相关知识
android 网络一般使用的都是 http 或 https,使用的网络框架一般为 volley 或者 retrofit,而他们封装的是 HttpURLConnection、HttpClient 或 okhttp,现在基本是 Retrofit + Okhttp 的模式,一般会配合RxJava一起使用。我们知道,http协议是基于TCP/IP协议而成的,TCP又是依赖于socket的,平常所说的TCP三次握手和四次挥手,也是这里用到的。说到TCP,那么还有TUP,这两个的区别一个稳定,一个不稳定;一个速度慢,原创 2021-04-26 21:14:53 · 567 阅读 · 0 评论 -
独立进程 WebView 的思路
WebView 是个占内存大户,它和图片是OOM的两大元凶,图片一般使用三方库来加载,统一管理app中图片的内存,那么 WebView 呢,对于它又怎么处理?一般情况都是在 Activity 中使用到它时,动态的 new 一个webview,然后通过代码 addView() 方法添加到容器中,在 Activity 销毁时,把它从容器中 removeView() 掉,同时 load() 个空字符串,以减少内存的泄漏。app可以有多个进程,一个主进程,其它的属于子进程,每个进程的内存上限是固定的,理论上进.原创 2021-04-07 20:36:39 · 1168 阅读 · 1 评论 -
BlockCanary 原理解析(1.5.0为例)
android UI流畅,界面是否卡顿,是很重要的体验。如果app有卡顿了,怎么排查呢?检查内存的有开源库 LeakCanary,那么UI卡顿有没有类似的库?还真有,就是 BlockCanary,它借鉴了 LeakCanary 的展示数据的思路。BlockCanary 的使用很简单,在 Application 中初始化一下即可。BlockCanary.install(this, new BlockCanaryContext()).start();看看它的代码 public static..原创 2021-03-26 19:54:46 · 492 阅读 · 0 评论 -
LeakCanary 原理分析
LeakCanary 以1.5版本为例子,简单分析其中的原理。 LeakCanary 可以检测App的内存泄漏,在我们自定义的 Application 的 onCreate() 方法中执行 LeakCanary.install(this); 这行代码即可。代码很简单,我们看看它做了什么 public static RefWatcher install(Application application) { return refWatcher(application).listenerServ...原创 2021-03-18 20:47:37 · 375 阅读 · 0 评论 -
RxJava 原理分析(重启)
以前写过 RxJava 源码分析,但是是直接对着源码分析流程,分析的也比较简单,这次从原理角度分析。 RxJava 是异步,网上介绍的都是订阅者模式,其实就是观察者模式的变种,我们先分析下 java 中自带的观察者接口 Observer 和被观察者 Observable。这两个类的代码比较简单,Observable 中有个集合,集合中存放的是 Observer,Observable 有个notifyObservers()方法,一旦调用,就会遍历集合,执行 Observer 对象的 update() 方法原创 2021-03-12 20:06:50 · 204 阅读 · 0 评论 -
Glide 中 Bitmap 的图片复用 (3.7.0为例 6)
Bitmap 在app应用中是个占内存的大块头,google 公司也一直对它做优化,比如说存储机制,Android 2.3.3及以前版本,Bitmap 的像素点数据是保存在 Native Memory(C/C++),Bitmap对象则是保存在 Dalvik heap(Java); 从Android 3.0开始,像素点数据与Bitmap对象一起存储在 Dalvik heap中。从 Android 8.0开始,Bitmap 的像素点数据又保存在Native Memory中。Android 3.0时,在 Bi原创 2021-03-10 20:56:52 · 913 阅读 · 0 评论 -
Glide 缓存机制分析二,内存缓存(3.7.0为例 5)
缓存分为磁盘和内存两种,上一篇讲了磁盘缓存,其中提到了图片缓存到本地后,在 EngineJob 中切回主线程,handleResultOnMainThread() 中会把图片缓存到内存中,同时把图片回调到上一层,传给view,这里注意下保存到内存中的方法 listener.onEngineJobComplete(key, engineResource) @Override public void onEngineJobComplete(Key key, EngineResource<...原创 2021-03-05 22:05:24 · 277 阅读 · 0 评论 -
Glide 缓存机制分析一,磁盘缓存(3.7.0为例 4)
上篇文章讲了图片网络的请求步骤,这一章说说缓存机制。Glide的缓存分为三大步:内存缓存、磁盘缓存以及服务器存储(或 drawable、Asset等),服务器也就是上一篇说的网络请求,这里就不说了;内存缓存是 软引用+LruCache缓存,磁盘缓存分为 原始图片缓存+转换后的图片缓存;内存缓存是通过 skipMemoryCache() 来控制是否开启,默认是开启状态,磁盘缓存则是通过 diskCacheStrategy() 方法,默认是 GenericRequestBuilder 中的 DiskCacheS原创 2021-03-04 20:00:48 · 384 阅读 · 1 评论 -
Glide 网络请求分析二(3.7.0为例 3)
上一篇中 Glide.with(this).load("http://p1.pstatp.com/large/166200019850062839d3").into(iv); 加载图片,load() 方法执行到 RequestManager 中的 private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass) { ModelLoader<T, InputStream&...原创 2021-03-03 20:28:35 · 444 阅读 · 1 评论 -
Glide 网络请求分析一(3.7.0为例 2)
Glide 加载图片,一般都是一行代码就搞定了,比如说在 Activity 中,简化一点的代码Glide.with(this).load("http://p1.pstatp.com/large/166200019850062839d3").into(iv);这里面有三个方法,with() 方法上一章讲了一个例子,现在重点看下 load() 的方法,Glide.with(this) 返回的对象是 RequestManager,它的方法代码为 public DrawableTypeRequest&...原创 2021-03-02 09:54:23 · 778 阅读 · 0 评论 -
Glide 生命周期绑定分析(3.7.0为例 1)
Glide 加载图片时,我们知道它会根据传入的上下文决定它的生命周期,如果传入的是 Activity 或 Fragment,那么如果页面隐藏或销毁时,图片还没从网络上获取成功,它会自己停止加载图片;该页面重新出现在前台时,会重新加载,那么 Glide 是怎么做到的呢?在 Activity 中添加一个 Fragment,Fragment 的生命周期会随着 Activity 的生命周期变化而变化;同样,Fragment 中也可以嵌套 Fragment。反应快的,看到这就反应过来了,Glide 其实就是通过 F.原创 2021-02-08 19:25:42 · 257 阅读 · 0 评论 -
Fragment 的懒加载分析(延迟加载数据,性能优化)
Fragment 使用已经很广泛了,它的生命周期比Activity的稍微复杂点,Fragment 不是 View,它的职责,更像是 MVP 模式中的 P。Fragment 经常嵌套于Activity中,或与 ViewPager 配套使用;ViewPager + Fragment 应该是最常用的一种使用方法,但也会引出一个问题,那就是 Fragment 延迟加载的优化。ViewPager 是有预加载机制的,默认提前加载下一个,这就导致在当前页面,会执行下一个页面Fragment的 onCreateVi.原创 2021-02-05 18:24:45 · 1078 阅读 · 0 评论 -
Menu 菜单中单个App显示多个任务列表预览视图
android 老款手机有三个物理键,新款的部分手机都把物理键给隐藏了,直接用虚拟键代替,但这三个键的功能是一样的,分别是 back 返回键、 Home 主界面键、Menu 菜单键。点击菜单键时,页面会出现app的列表预览图,通常情况下,每个app有一个预览图,如果我们想让一个app显示两个或多个预览图,该怎么办?比如说我们的App中有两个页面 Activity1 和 Activity2,打开顺序是从 1 跳转到 2,我们想让这两个页面都显示在任务列表预览视图中,通常的做法是通过 Intent 来设置.原创 2021-01-20 18:17:33 · 545 阅读 · 2 评论 -
并发时用到的关键字 volatile
volatile 这个关键字,接触最多的场景是单利,单利中对 instance 做修饰,这个词怎么解释?知道看了一个例子,才明白些。并发中,如果两个线程不停的对一个成员变量赋值,会产生什么效果呢? static boolean flag; static class ThreadA extends Thread { @Override public void run() { while (true) { ...原创 2020-12-28 15:37:25 · 139 阅读 · 0 评论 -
Semaphore 的细节及用法
Semaphore 是并发工具类,我们在一些需要并发的地方会用到它。之前也有文章提到它,当时么有探讨一些细节,给出两个例子:https://blog.csdn.net/Deaht_Huimie/article/details/105628723 。 这篇文章直接从后半部分开始看就行了。今天讲些细节,算是个复盘。Semaphore semp = new Semaphore(1); 这行代码中,Semaphore 的许可数字是1,意思是在获得许可(acquire())后,同一时间只允许一个可用,其他的就.原创 2020-11-27 21:00:02 · 439 阅读 · 0 评论 -
内存泄漏查找及分析
android 内存泄漏是个常见的问题,一不留神就出现了,内存泄漏说白了就是生命周期超了,有经验的童鞋,在写代码时就会注意了,但人无完人,难免会失手,下面就说说怎么排查内存泄漏问题。常见的无外乎两种, Android Studio 开发工具自带的 Profiler,或者直接使用 LeakCanary 开源库。先说说 Profiler。Profiler 栏目有三个小栏目,CPU 、MEMORY 、NETWORK,分别指:CPU使用状况,内存使用状况和网络状况,内存分析选择 MEMORY,此时在它右边可以看原创 2020-11-13 22:30:26 · 284 阅读 · 0 评论 -
android 获取屏幕的高度(软键盘的影响)
部分手机,尤其是华为手机,底部会出现一个软键盘,这个是是可以设置的,让其消失,以下以华为手机为例说明。通常我们获取屏幕的宽高有几种方法,通用的有 public static int getScreenHeight(Context context) { DisplayMetrics dm = new DisplayMetrics(); WindowManager wm = (WindowManager) context.getSystemService(Conte...原创 2020-10-21 21:07:20 · 720 阅读 · 0 评论 -
android 帧动画如何进行优化
android 动画有几种不同的类型,其中有一种是帧动画。实现它的方式也有几种,一种是直接作出 gif 或 webP 格式的图片,直接播放;一种则是 android 系统提供封装好的方法,将动画定义在 xml 中,用 animation-list 标签来实现它,<animation-list> 元素是必要的,可以包含n个 <item> 元素,每个 item 代表一帧动画。 以上两种都能实现,但比较耗费内存,想想看,假如说帧动画有 100 张图片,每张图片都比较大的情况下,此时执行动画原创 2020-09-24 20:56:43 · 1955 阅读 · 0 评论 -
android 马甲包中的 so 文件适配
项目中经常会用到三方库,包括 jar 、arr 或者 so 文件,对于它们的使用,我们常是将 jar和arr 直接放到项目目录 \app\libs 下即可,对于so文件则是 \app\src\main\jniLibs\ 下面对应的 armeabi-v7a 、armeabi 等目录下,以上是默认的情况。我们如果想修改so文件的目录,可以通过 gradle 来修改,gradle 可以对 jni 的目录做个修改,比如我们想把 so 文件也放在 \app\libs 目录下,则可以android{ ……...原创 2020-08-31 19:27:16 · 281 阅读 · 0 评论 -
提高 Activity 跳转速度
从一个页面跳转到另外一个页面,这在 Android 中是很常见的操作;有的页面跳转是瞬间打开,有的是会微微钝一下才打开;或者在页面里弹出一个 Dialog 弹框,明明已经调用完了 show()方法,但弹框没马上弹出来,延迟了一百多毫秒才显示出来,这样给人的体验就很不好了。为什么会出现这种情况呢?页面跳转迟钝和弹框的展示延迟的原因都一样,基本分为两大类。第一类就是看看是否在UI线程左耗时操作,这个经常是数据方面的问题,比如说要从数据库里面查询数据,或者说对数据做了一些复杂逻辑的操作,例如要对集合中的数据,原创 2020-08-25 19:36:29 · 2483 阅读 · 0 评论 -
android 如何绕过签名校验
上一章我们说了签名的一些基本信息,这一章说说它的用法。我们知道 android 存在二次打包的现象,这样可以篡改一些功能,所以部分app会在一些重要功能或者接口请求或者程序的入口的地方使用签名校验,校验下 SHA1 或 MD5 等信息,看看是否是自己原始的签名,如果不是,则强制程序退出。这个属于安全防御,自然有盾就有矛,现在就探讨一下怎么绕过签名校验,也就是常说的 hook 。所谓 hook ,也就是通过反射和动态代理,做一些常规做不到的操作,比如替换对象的属性值,或者拦截对象的方法等等,现在先说个.原创 2020-07-29 14:47:59 · 6196 阅读 · 4 评论 -
android 的签名问题简介
我们知道,apk 是需要一个签名的,签名 Eclipse 时用的是 keystore, Android Studio 用的是 jks。为什么要签名呢?一是开发者的身份验证,相同的包名必须是相同的签名才能替换安装;二是基于安全考虑,防止代码被篡改。android 程序都必须要有数字证书,并且android手机安装apk时,apk都必须是被签名过的。AS 使用debug默认运行时,AS 提供了一个默认的签名,如果没有配置的话,不同电脑上的默认签名也是不同的;同理,同一台电脑上,不同程序的默认签名是相同的。原创 2020-07-25 17:49:32 · 193 阅读 · 0 评论 -
穿山甲和广点通激励视频广告打开失败的异常处理
由于项目里接入了广告,包括但不限于穿山甲sdk和广点通sdk,视频广告是收益比较高的广告,项目里面出现的地方比较多。流程一般都是UI上有个按钮,点击按钮,请求到激励视频广告,然后直接打开该广告,也就是跳转到广告视频页面,等广告播放结束后,会有关闭按钮,点击关闭按钮,广告sdk会触发暴露出来的回调;如果请求广告失败,我们自己也会处理;这两种情况我们都是可以掌控的,也就是说这两种情况,我们都会有方法接收到事件,我们可以根据相应的事件,做出下一步的处理,比如给用户发奖励,或者重新请求广告。打开广告激励视频的方原创 2020-06-22 19:10:45 · 20397 阅读 · 3 评论 -
JetPack 之 LiveData 使用及源码分析
LiveData 是在 Lifecycle 的基础上发展起来的,我们看看例子可以知道,需要借助于 ViewModel,我们来看个例子public class LDActivity extends AppCompatActivity implements View.OnClickListener{ private final static String TAG = "LDActivity"; private NameViewModel model; TextView name...原创 2020-06-08 09:23:05 · 286 阅读 · 0 评论 -
JetPack 之 Lifecycle 处理生命周期
在 Android 中,声明周期是个很重要的概念,内存泄漏都是因为声明周期没处理好导致的, Jetpack 中推出的 LifeCycle ,可以说是专门为了处理各种控件的声明周期存在的。它使用起来也很简单,就是个观察者模式,通过注解来实现的功能,先举个例子。本例子用的是sdk版本是29。public class LifeDaActivity extends AppCompatActivity { static final String TAG = "LifeDaActivity"; ...原创 2020-06-03 21:22:57 · 1318 阅读 · 0 评论 -
JetPack 之 DataBinding 的使用
android 几年前推出了 Jetpack 控件,其中有个 DataBinding ,这个框架能极大的简化我们需要写 findViewById()、setText()、setVisibility()、setEnabled() 以及 setOnClickListener() 等等方法,避免我们写一大堆代码。这个框架也比较好用,直接在 build.gradle 中配置以下脚本即可android { ... dataBinding { enabled = true ...原创 2020-05-29 19:50:57 · 316 阅读 · 0 评论 -
android 自定义控件之文字(新闻热门置顶等标签的效果)
之前项目中有个需求,需要在同一行展示n个标签,标签内容有 热门、置顶、广告、促销、精致 等等,都是两个字的词语,并且标签外面需要有个圆角矩形包裹起来,我们可以直接看今日头条的主界面的样式,见下图,途中只有一个标签我们项目中的情况与这个类似,也是一个列表,列表中的 item 的最下面的一行,显示标签,标签后面是一些时间和商店名等信息。根据条目内容,标签可能为1个、2个、3个或者一个都没有,我接手项目时,这个功能已经实现了。只是列表在上下滑动时,尤其是快速滑动,会有卡滞的感觉,我看了看适配器的代码,发现原创 2020-05-15 20:20:38 · 546 阅读 · 0 评论 -
Android 中 gradle 之 groovy
Aandroid Studio 中使用 gradle 来管理一些信息,最早接触时感觉挺麻烦的,后来才逐渐感觉到它的厉害之处。前几年项目中接入了热修复 Tinker,我看了看它的源码,更感觉到脚本的厉害,还能动态的往 AndroidManifest 中添加一些信息,比如 <meta-data /> 等,我就好奇了,决定研究一下 groovy。看别的资料说它和 Java 很类似,能在 AS 中直接运行,那我就开始写 Demo。首先创建个项目,然后创建个 module,我用的是 Java Li.原创 2020-05-12 19:33:28 · 512 阅读 · 0 评论 -
组件化的基础知识
组件化的概念,在几年前就提了出来,并且衍生出些框架,那么什么是组件化,为什么要用组件化?如果我们移动端项目比较小的话,团队人也不多,一般情况下,业务逻辑也不会复杂,此时,按照常规写代码,没什么问题。但项目一旦大了,就像我们团队,android 开发十几个人,逻辑也比较乱,一个按钮的显示就会被好几个逻辑控制,这种情况,如果几个人的功能有交集,很难说不会因为自己的改动而影响别人的逻辑;随着代码量的增加,编译一次的时间也大大增加。这时候,如果把业务逻辑进行拆分,拆到n个不同的module中,每个module中做自原创 2020-05-08 20:12:39 · 433 阅读 · 0 评论 -
AOP 在android中的使用之埋点日志
android 开发,我们通常使用的是面向对象编程,这个写起来比较方便。但一些特殊的功能,比如说埋点统计些信息,或者打印某些方法的消耗时间,如果我们在要统计的地方直接写代码,看着不优雅,并且也把功能耦合在一起了。AOP 叫做切面编程,它更像一把刀切入到某个功能里面,不用直接耦合代码。比如如打印耗时日志,使用切面编程则可以把要统计的一些方法的代码统一放在一个地方,通过注解来引用,这样就比较完美的做到...原创 2020-04-29 21:13:43 · 906 阅读 · 0 评论 -
Tinker 热修复引出的 Apt 功能及使用(定制 Application)
android 项目,稍微大一点的,都希望接入热修复,好处是如果有bug,可以随时修复,不用重新发版本升级;同时,也希望对发出去的版本添加一些新功能。H5是可以做到随时更新,但牵涉到原生的交互,就没那么容易了,因此,前几年热修复是个热门。我所在的项目组是2016年底时添加了热修复功能,一开始是说要自己公司做一个,接到任务的那哥们脸色发白,连续两周,基本没什么产出。我俩工位挨在,我见证了那哥们的崩溃...原创 2020-04-26 20:50:00 · 377 阅读 · 0 评论 -
并发工具类 CountDownLatch、CyclicBarrier、Semaphore 的用法
android 开发,我们会遇到一些并发场景,虽然不多,但还是有的。我们可以自己写代码解决并发问题,也可以借助java提供的工具类。接下来就介绍几个类及它们的使用场景。CountDownLatch 是 java 1.5 时被引入的,它的作用是使一个线程等其他线程执行完毕后再执行,这么介绍听起来比较抽象,那举个具体的栗子:在android开发中,某个界面显示数据需要请求接口,但此时不是一个接口,...原创 2020-04-20 10:27:00 · 432 阅读 · 0 评论 -
广点通sdk广告中的激励视频关闭按钮引发的bug排查及解决
前几篇写过穿山甲sdk激励视频按钮丢失回调的问题,今天说说广点通sdk激励视频的问题。可以先看看前文:https://blog.csdn.net/Deaht_Huimie/article/details/104035669 ,然后再看本篇文章,这两篇文章给大伙起到抛砖引玉的作用。由于穿山甲sdk蹦出的关闭按钮问题,那么我很自然的想到了广点通sdk的激励视频是否也存在相同的问题...原创 2020-04-02 21:46:15 · 6539 阅读 · 0 评论 -
ViewStub 使用及源码解析
我们知道布局优化有三个标签,include 、merge 和 ViewStub。 我们可以把公共的布局抽取到一个 xml 中,然后使用 include 来引用; 布局会分层次,如果里层和上一层是同样的容器,则可以使用 merge,但记住一点,merge 一定是在根节点; ViewStub 不是关键字,而是 View 的一个子类,它的作用是占坑,延迟加载它里面引用的布局。详细说说 ViewStub ...原创 2020-03-10 20:31:52 · 1379 阅读 · 0 评论 -
Toast 为什么会造成内存泄漏
我们知道,在使用 Toast 时,如果第一个参数传入的是 Activity 的话,可能会造成内存泄漏,只要把 Activity 改为 Application 即可解决问题,那么为什么会造成内存泄漏呢?前文分析过 Toast 的源码及执行流程,这里再简单复述一遍,我们先看看调用的方法 public static Toast makeText(Context context, Cha...原创 2020-02-21 20:44:56 · 5499 阅读 · 4 评论 -
穿山甲sdk激励视频广告关闭按钮引发的bug排查及解决
项目中接入了穿山甲广告,其中包括图文广告和视频广告,后期发现一个偶现的问题,就是看完激励视频广告后,点击视频页面的关闭按钮,此时回到了app源生页面,UI卡住了,本来看完视频有个加分操作,现在没了。排查了代码,看看是不是自己的代码有漏洞,看了半天也没发现,然后就想,是不是穿山甲sdk的视频有问题,点击关闭按钮没有给客户端回调?为了验证这个问题,我写了个点击事件,请求激励视频并且播放,在穿山甲的回调...原创 2020-01-19 02:48:03 · 32420 阅读 · 4 评论 -
android 中动态加载广告sdk
关于动态加载sdk的话题,网上介绍比较多;今天通过第三方工具来取个巧,虽然方法也有点不太靠谱,但终归是一个思路。项目里面接入了穿山甲sdk和广点通sdk广告,结果放到应用市场时说被拒了,因为有广告,所以产品同学问能把广告动态下发吗,一天时间够吗?我心中的是一万匹羊驼跑过,先不说应用市场是怎么检测的,如果是检测 Manifest 就惨了,基本没办法;现在先假设没检查配置清单,怎么办呢?项目里接过...原创 2020-01-13 21:57:48 · 1224 阅读 · 1 评论 -
kotlin 中的数据类型、泛型、枚举
Kotlin 中可以创建包含数据的类,使用的关键字为 data,比如说 data class Student(val name: String, val age: Int),编译器会自动重写 equals() 、 hashCode() 、toString() 等方法fun test(){ val u = Student("tom", 15) val u1 = Student(...原创 2019-12-14 21:59:58 · 500 阅读 · 0 评论