那些年,我们一起踩过的 “Android 坑”

69、多线程同时访问集合(ConcurrentModificationException)

问题现象:

多线程同时修改集合时常常容易出现 ConcurrentModificationException ,即便是改成用 Collections.synchronizedCollection() 方法同步也无效。

原因分析:

当集合正在迭代时,如果进行修改就会出现异常,@问题13 已经说过该问题。而 synchronizedCollection() 方法虽然对部分操作加上了 synchronized 关键字以保证线程安全,但其 iterator() 操作不是线程安全的,在迭代时操作依然会出现异常,并且效率也比较低。

解决方法:

在 Java 中早已有比较好的替代对象,相比起来有更加细化的锁机制,效率更高,不会出现 ConcurrentModificationException 异常。

  • ConcurrentHashMap 为 Map 的同步,设计与实现非常精巧,很适合学习
  • CopyOnWriteArrayList 为 List 的同步,采用写入时复制的方式避开并发问题,当修改操作较多时性能上会有比较大的代价

68、Facebook 或 Twitter 自定义登陆按钮样式

问题现象:

使用官方的 SDK 做登陆时,只提供了登陆按钮作为跳转入口,但是样式和设计图有很大出入,直接设置按钮的样式很难达到想要的效果。

原因分析:

官方应该是推荐登陆时使用默认的样式,这样来避免或达到某些目的。虽然尽力想用默认的样式,不过由于与 UI 的其它部分太不搭了,还是决定自定义。

解决方法:

先将官方按钮设置为不可见,然后自定义效果样式按钮,并将点击事件实现为触发官方按钮的点击事件,如下:

<com.twitter.sdk.android.core.identity.TwitterLoginButton
    android:visibility="invisible" />

// 或使用 performClick() 方法
twitterLoginButton.callOnClick();

67、Android 5.0 的通知栏 SmallIcon 的 BUG

问题现象:

android.app.RemoteServiceException: Bad notification posted from package xxx.xxx.xxx: 
Couldn't create icon: StatusBarIcon(xxx.xxxx)

原因分析:

算作是 Android5.0 的 Bug,在 android4.4 和 6.0 中都正常。

解决方法:

if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP
    || Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1){
    iconId = mContext.getApplicationInfo().icon;
}
NotificationCompat.Builder.setSmallIcon(iconId)

66、ScrollView与RecyclerView嵌套后的冲突问题

问题现象:
我们以前在使用GridView,ListView与ScrollView嵌套时一定有遇到显示不全或者滑动冲突等问题,
在我们的RecyclerView使用中仍然难逃此劫,甚至有的时候会有卡顿的问题。下面我们介绍一下如何解决这个问题

原因分析:

同理与ListView与GridView相同

解决方法:

1、卡顿,滑动不流畅问题。

首先解决卡顿的问题使用mRecyclerView.setNestedScrollingEnabled(false);
这个目前是最优解

2、显示不全(6.0以上容易出现此问题)

方法一:在Recycler的父布局中添加RelativeLayout隔离,不用像一些博客说的那样进行高度计算和 OnMeasured()重写。(未解决尝试方式二)

方法二:将你的ScrollView替换成android.support.v4.widget.NestedScrollView,此方法对此问题有优化(未解决尝试方式三)

方法三:如上还未解决或者只显示一行,把design库和V7库升级到23.2以上,然后加上如下代码
mLinearLayoutManager.setSmoothScrollbarEnabled(true);
mLinearLayoutManager.setAutoMeasureEnabled(true);
mRecuclerView.setLayoutManager(mLinearLayoutManager);
mRecuclerView.setHasFixedSize(true);
mRecuclerView.setNestedScrollingEnabled(false);

如果还未解决,或者只显示一行,你可以核对一下你的适配器子布局中高度是否使用了
android:layout_height=”match_parent”

65、Android Studio 3.0 编译项目无法找到 Gradle

问题现象:
build.gradle 文件:

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
   
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0-alpha3'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
allprojects {
    repositories {
        jcenter()
        maven { url 'https://jitpack.io' }
    }
}
task clean(type: Delete) {
    delete rootProject.buildDir
}

Android Studio 3.0 Canary 3 编译项目提醒:

Error:Could not find com.android.tools.build:gradle:3.0.0-alpha2.
Searched in the following locations:
    file:/Applications/Android Studio 3.0 Preview.app/Contents/gradle/m2repository/com/android/tools/build/gradle/3.0.0-alpha2/gradle-3.0.0-alpha2.pom
    file:/Applications/Android Studio 3.0 Preview.app/Contents/gradle/m2repository/com/android/tools/build/gradle/3.0.0-alpha2/gradle-3.0.0-alpha2.jar
    https://jcenter.bintray.com/com/android/tools/build/gradle/3.0.0-alpha2/gradle-3.0.0-alpha2.pom
    https://jcenter.bintray.com/com/android/tools/build/gradle/3.0.0-alpha2/gradle-3.0.0-alpha2.jar
Required by:
    project :

原因分析:找不到,可能是网络或者服务器问题,最终定位到是 Google 更新了针对 Android Gradle 编译的仓库地址有更新。

解决方法:我们需要在 build.gradle 文件中追加:

repositories {
   maven {
       url "https://maven.google.com"
   }
}

官方文档说明:
https://android-developers.googleblog.com/2017/05/android-studio-3-0-canary1.html

64、编译时出现jar包内包含相同的文件

问题现象:
我在项目中添加了一些jar的引用,但在编译的时候发现存在相同的文件,导致编译失败。
原因分析:

Error:Execution failed for task ‘:app:transformResourcesWithMergeJavaResForDebug’.
com.android.build.api.transform.TransformException: com.android.builder.packaging.DuplicateFileException: Duplicate files copied in APK META-INF/*.properties

解决方法:
如果依赖的jar使用多次引用版本不同的jar包,那么最好的办法是选择留下最合适的版本jar包。小概率是因为使用不是相同的jar包时出现了文件冲突问题,这时候在build.gradle中添加packagingOptions就能解决。

packagingOptions { 
     exclude 'META-INF/***.properties      }

63、关于so库使用小总结

问题现象:
应用中新添加了so库,在32位处理器上没有问题,跑64处理器的时候出现了UnsatisfiedLinkError的问题,查看了异常是lib64的so库没有找到,之后添加了ndk的配置后,成功在64处理器上跑通,但发现library里的so库受到影响,加载失败。
原因分析:

java.lang.UnsatisfiedLinkError:dalvik.system.PathClassLoader
java.lang.UnsatisfiedLinkError:No implementation found for void io.vov…. MedioPlayer.native_init()

第一个异常里面有lib64 so 没有发现,直接找64和32位的问题,第二个
问题指向的是一个native方法init失败,打包apk发现只有armeabi中的so库,而library中为了优化性能和文件大小,只在armeabi留下一个库,其他都放在了其他文件夹中。
解决方法:
处理64位兼容上,使用了兼容armeabi的方法,在build.gradle中添加了

   ndk {
    abiFilters "armeabi"
    } 

由于library中armeabi只有一个so库,所以加载失败了。原因是指定要ndk需要兼容的架构(这样其他依赖包里mips,x86,armeabi,arm-v8之类的so会被过滤掉),所以在上面添加了

    ndk {
    abiFilters "armeabi", "x86","armeabi-v7a"
    }

这样就能兼容我使用的库中的所有so,但还是担心后面有加载库失败的问题,查看了网上abi的资料,没问题。
在项目只包含了 armeabi,那么在所有Android设备都可以运行; 如果项目只包含了 armeabi-v7a,除armeabi架构的设备外都可以运行; 如果项目只包含了 x86,那么armeabi架构和armeabi-v7a的Android设备是无法运行的; 如果同时包含了 armeabi, armeabi-v7a和x86,所有设备都可以运行,程序在运行的时候去加载不同平台对应的so,这是较为完美的一种解决方案,同时也会导致包变大。

62、Google Play Store 过滤问题总结

说明:当用户在 Google Play 上搜索或浏览应用以下载时,会根据哪些应用与其设备兼容来过滤搜索结果。例如,如果应用需要摄像头,Google Play 不会在没有摄像头的设备上显示该应用。这种过滤帮助开发者管理其应用的分发,并且有助于确保为用户提供最佳的体验

过滤规则 : https://developer.android.com/google/play/filters.html?hl=zh-cn

注:需要硬件支持的权限也会默认进行设备兼容过滤;

如何去掉指定功能设备兼容过滤 :

Nexus 7 没有电话功能 ,然而在应用的 Manifest 文件里声明了电话相关的权限,希望不支持电话功能的设备也能搜索该 APP
,就在 Manifest 文件添加如下代码 :

<uses-feature android:name="android.hardware.telephony" android:required="false"/>

注:通过显式声明某项功能并加入 android:required=”false” 属性,可以在 Google Play 上有效停用所有针对指定功能的过滤。

更多功能声明 : https://developer.android.com/guide/topics/manifest/uses-feature-element.html?hl=zh-cn#permissions-features

61、媒按键监听,Android5.0+ 不同的监听方式

使用场景描述:
应用中需要播放音乐的时候,通常有个令人捉急的问题就是媒体焦点;假如同时用 QQ音乐 与自己的应用同时播放音乐的时候,媒体焦点到底花落谁家,谁能够响应这次媒体按键;这就要看谁最后申请了这个焦点

以往的方式都是通过广播的形式,来看看 Android 5.0+ 的注册方式

     int res
  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JackWaiting

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值