抬头仰望星空,是否能发现自己的渺小。

伪斜杠青年

人们总是混淆了欲望和理想

2020.10 第二周目 踩坑小记

很多时候所以为的原因,实际上只是表层现象

Context类型不同导致的 Dialog 崩溃

背景:Dialog 中弹出 Dialog,传递的 context 为 activity 的 context。

问题:在部分 MIUI 机型上提示“Permission Denied Activity”,现象上与小米的「后台弹出界面权限」有关。但实际上是在前台弹出。

解决思路:我只看到了后台权限的这个现象,搞了挺久,但是不尽人意,因为理论上不需要申请权限,毕竟都在前台。后来老大过来,debug 发现那台手机在 dialog 初始化时的 context 变成了 contextWrapper。

解决办法:判断 dialog 初始化时的 context 是否为 contextWrapper,如果是则使用 context.baseContext 来获取 activity 的 context。否则直接使用 activity 的 context 即可。

问题机型:Redmi 6 MIUI11 安卓9

各种 dir 配置问题

移步:各种 Android 常用 dir 在 gradle 中的配置方式

SDK 接入耗时问题 :文档阅读不仔细

在接入某个 SDK 的时候遇到了一些麻烦,搞了挺久,被自己坑了

  • 一些运行时的错误,是自己将 support 条件写反了导致没有初始化(自己居然没发现,一个劲儿的思维定势去看报错信息,傻了)
  • 另外无法正常运行的授权失败的原因是“包名不匹配”,而这在文档的最底部写得清清楚楚,但是我却因为心急而漏看了(捡芝麻丢西瓜)。

!!!要细心啊!!!

异常的加载缓慢问题

原因:

项目里有一个公司自己封装的异步框架,项目越来越大,内部的异步处理的 runnable 也越来越多,以至于未知原因阻塞导致数据一直无法加载。比较奇怪的是只在部分手机上会这样,大概是与线程池的分配有关,没去细纠,用协程替代了。

解题思路:

将项目流程的主要位置使用 log 记录,找出耗时最长的位置再进行判断

一个 ktx 库引用错误问题

移步:More than one file was found with OS independent path ‘META-INF/proguard/coroutines.pro’

一次广告调用时序导致份长耗时问题

背景:

正常逻辑,ActivityA -> pickImage -> return ActivityA -> show image temp and crop(覆盖在 activity 上,但属于 activity 的上层布局)-> done 按钮 -> ActivityA

加了广告后:

ActivityA -> pickImage -> return ActivityA -> show image temp and crop(覆盖在 activity 上,但属于 activity 的上层布局)-> done 按钮 -> Ad activity -> ActivityA

问题复现:不加广告不会有问题、加广告就出现了问题,说明逻辑上本身没有问题。

一番拼命 debug 也没解决,只知道原因是因为需要拿一个crop 的 view 范围,但 view 拿到的 各种 left、right、top 等都是0,大概猜到是没有绘制,但逻辑很是复杂。

最后,老大给了个方案,让 ad 观看完后的事件使用 post 去发送,结果没想到成了,后面分析,是因为 ad 将 ActivityA 覆盖了,导致返回时设置的 view 的相关参数并没有完成绘制,因为 activity 本身也并没绘制完,加上这中间还有一些数据计算操作。

反思:确实是迷,但这过程中我也是有发现并没调用相关 addOnGlobalLayoutListener 回调,但我没能想到activity 本身可能都没初始化完成。经验差距?

Windows 文件被占用

先按标准的快捷键,按出任务管理器,切换到 cpu Tab,底下有个资源监视器。

打开后,会看到一个大大的输入框:“关联的句柄”,输入被占用的文件名的一部分就可以过滤出来了,然后右键结束那个进程即可。Windows 真是糟心。

分析 Activity 的一些启动流程

接手别人项目的时候,遇到奇怪的跳转问题,除了分析其调用逻辑,还得多看看堆栈,才能和逻辑对上。直接打印 activity 堆栈看看吧,或许很有帮助。

adb shell dumpsys activity

怎么分析呢,找包名,找 stack,一个 stack 中有相关的一个或者多个 activity,很好辨别。

Android 包瘦身?

公司的 apk 包很大,大得离谱,去找了下相关瘦身操作才知道,公司实际上已经把这些操作做到极致了,最后怎么解?还是得从不用的库开始,注释代码,少依赖。

美团的这篇文章可以看看:

Android App包瘦身优化实践

资源方面一般都是配合 AndResGuard + 7zip 的重新压缩。

这里可以使用 gradle 分析依赖:

 ./gradlew :app:dependencies 

可以输出到某个文件,mac 路径上略有不同,但更方便,但都是用>

 ./gradlew :app:dependencies > d:out.txt

参考:使用Gradle查看Android依赖树图

参考:Android 性能优化实战篇 — APK 瘦身

You must not call setTag() on a view Glide is targeting

在解一个 rv 的图片加载错乱时候,用了 setTag,本来 Glide 会自己去用这种方式解决错位问题,但我们这里只是用来获取 bitmap,so,需要自己设置 tag,但没想到,有个惊喜: You must not call setTag() on a view Glide is targeting

解决办法也很简单,在项目中也找到了,就是在 res/values/ids.xml中自己定义一个 ids,然后使用

setTag(R.id.your_id,"some content")
val some_content = getTag(R.id.your_id)

即可。

Android 设置壁纸

无论动态静态,对于三方应用其实都没有什么尽善尽美的办法,还是官方的主题中心靠谱,代码别处找找即可。

比如:Android 代码设置壁纸的方式,兼容各大ROM

kotlin 协程混淆问题

网上很多:但这种问题,谷歌自己干嘛不解决?

-keep class kotlin.** { *; }
-keep class kotlin.Metadata { *; }
-dontwarn kotlin.**
-keepclassmembers class **$WhenMappings {
    <fields>;
}
-keepclassmembers class kotlin.Metadata {
    public <methods>;
}
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
    static void checkParameterIsNotNull(java.lang.Object, java.lang.String);
}
-keep class kotlinx.coroutines.android.** {*;}
# ServiceLoader support
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
-keepnames class kotlinx.coroutines.android.AndroidExceptionPreHandler {}
-keepnames class kotlinx.coroutines.android.AndroidDispatcherFactory {}

# Most of volatile fields are updated with AFU and should not be mangled
-keepclassmembernames class kotlinx.** {
    volatile <fields>;
}

TabLayout 与 ViewPage联动

可以使用TabLayoutMediator

官方文档:使用 TabLayout 添加标签页


0条评论

发表评论