IntelliJ IDEA 提示 'try' can use automatic resource management,Java7新特性

IntelliJ IDEA会提示

Java 7 build 105版本开始,Java 7的编译器和运行环境支持新的try-with-resources语句,称为ARM 块(Automatic Resource Management) ,自动资源管理。

新的语句支持包括流以及任何可关闭的资源。

使用try-with-resources语句来简化代码如下: 

在这个例子中,数据流会在try执行完毕后自动被关闭,前提是,这些可关闭的资源必须实现java.lang.AutoCloseable接口。

注:目前java.lang.AutoCloseable接口的子接口或实现类如下:

所有已经子接口: 

 所有已知实现类: 

参考链接


在macOS Catalina(10.15.5)上搭建Flutter开发环境

下载并安装目前最新的Android Studio 4.0,然后通过Android Studio 4.0安装Android SDK

下载目前最新的flutter

配置环境变量

上述环境变量,全部追加到 .bashrc 尾部

如果不增加到.bashrc 尾部,则在 Android Studio 4.0 创建项目的时候,会非常慢,主要是网络问题。

必要的环境配置,依赖下载

继续阅读在macOS Catalina(10.15.5)上搭建Flutter开发环境

在Android Studio 4.X下查看窗口布局层次Hierarchy Viewer/Layout Inspector

在Android开发的时候,又是需要检查窗口布局层次,观察布局是否显示正确。

早期版本是使用Hierarchy Viewer ,最新的Android Studio 4.X下,我们使用 Layout Inspector,具体操作参考下图:

继续阅读在Android Studio 4.X下查看窗口布局层次Hierarchy Viewer/Layout Inspector

屏幕旋转的适配问题以及遇到的一些坑

在手机APP开发的时候,一般默认会适配竖屏,游戏开发除外。但是在Android平板电脑开发中,屏幕旋转的问题比较退出,可以这样说,平板电脑的最初用意就是横屏使用的,比较方便,用户会经常旋转我们的屏幕。

这里主要针对平板开发中的一些问题做一些总结。

1. 防止屏幕旋转之后,Activity的销毁问题

为了适配屏幕,Activity默认在屏幕旋转之后会销毁并且重建,但是这种情况会造成用户输入数据的丢失(需要开发者手动去保存和恢复,会带来一定的工作量),Activity毕竟是重量级的组件,它的销毁和重建会使得性能的下降,因此我们需要防止Activity的销毁和重建。

做法

在清单文件中为Activity添加一些配置,configChanges属性添加orientation|screenSize:

通过上述的配置可以防止Activity的销毁和重建。

注意:这里的 screenSize 经常被我们遗漏。一般我们都是设置 orientation , 当屏幕方向改变的时候不要重新创建。那么 screenSize 什么时候发生呢? 目前最常见的就是 系统导航方式 变化的时候,目前Android手机支持 手势导航 / 屏幕内三键导航 两种模式。这两种模式的不同就是在屏幕底部是否出现 Back/ Home / Menu。这样导致应用的显示高度发生变化,从而触发 screenSize

注意,辅助功能 里的 无障碍 模式下 导航模式 会被切换到 屏幕内三键导航 模式,从而引起窗口的重新绘制。

2. View屏幕旋转适配

除了制作横屏和竖屏两份布局文件的方法之外,如果我们的View是动态添加到Window的,屏幕旋转之后,我们的界面以及View需要做一些变动以适应屏幕。

我们可以复写Activity的onConfigurationChanged方法,并且在里面修改一些东西。

这里举个例子,如说我们的ListView右边有一个字母索引控件,这个控件是直接new出来并且是直接覆盖在ListView上面的。当屏幕旋转之后,这个字母索引控件的位置需要刷新(重新布局以及绘制)。因为这个控件是在我们的ListView的右侧,并且竖直方向居中。这时候我们就需要动态获取屏幕上的ListView的宽高,然后才能计算出字母控件应该布局的位置。

但是这里我们会遇到一些坑

直接通过View的getWidth方法或者先measure然后通过getMeasuredWidth方法获取到的宽都是错误的,获取到的是屏幕旋转之前的值,如下面的代码所示。但是我需要的是ListView实时的宽高值,这时候我们只能手动去计算。例如我们要获取ListView的高度,那么我们可以先拿到Window的总高度,然后减去状态栏、Toolbar的高度来获取(这里只是一个例子,具体做法需要具体分析)。

屏幕旋转的不确定性问题

最近又遇到屏幕旋转相关的新的问题,因此记录下来。我们知道,在Activity、View、Fragment等旋转的时候,如果你在清单文件中配置不重新创建的话,就会调用onConfigurationChanged方法。

但是问题来了,这个问题有一些不确定性因素,比如说当你的页面或者View被遮挡住(Stop)的时候就不会回调onConfigurationChanged这个方法。这比较略坑,会带来一些UI的偶发性问题。

解决办法就是我们自定义一个广播接受者专门用来接受onConfigurationChanged这个广播,这样子就可以确保,无论什么情况下,系统ConfigurationChanged的时候你的代码都会被执行。

自定义的ConfigurationChangeReceiver如下,这里提供一个静态方法方便注册。

接下类在Activity或者Fragment中的正确位置注册(onAttachedToWindow、onDetachedFromWindow):

记得反注册,防止内存泄漏哦。

参考链接


屏幕旋转的适配问题以及遇到的一些坑

Android默认调试签名证书

今天遇到了需要手工用调试签名重新签名APK文件的一个需求。

Android默认调试签名证书位置

Windows:

macOS Catalina:

证书密码 :android

签名脚本:

参考链接


Cannot resolve symbol KeyEventCompat(android.support.v4.view.KeyEventCompat找不到)

今天我把support版本升到了28.0.0  发现V4包  下的KeyEventCompat 类找不到了

com.android.support:appcompat-v4:28.0.0

那是因为KeyEventCompat类被取消了 hasNoModifiers() 方法已经被KeyEvent实现了

修改为:

参考链接


Android Q(Android 10)适配

应用读取 Device_ID

Android Q 之前有如下代码,获取设备Id,IMEI等

添加下面权限,并且需要动态申请权限

在 Android Q 上调用上面方法会报错

或者

在 Android Q 上上面方法已经不能使用了,如果获取设备唯一Id,需要使用其他方式了,谷歌提供的获取唯一标识符做法见 文档,也可以用Android_ID,上面这些也不是绝对能得到一个永远不变的Id,可能需要多种方案获取其他Id,比如有谷歌商店的手机可以使用谷歌提供的广告Id,还有其他厂商一般都会提供手机的一个唯一Id,我们项目现在使用下面这种方式 参考链接,后面会多测试一下。

 

参考链接


error=86, Bad CPU type in executable

最近在维护一个N久的项目时,发现在mac升级系统为10.15.5后(Android Studio 4.0,gradle 2.3.1),编译失败了,报错如下:

原因是最新版本的macOS Catalina(10.15.5)已经不支持32位的应用了,只能运行64位的应用。

解决方法:升级工程的buildToolsVersion,本例中将23.0.1 升级成25.0.3

参考链接


error=86, Bad CPU type in executable

Android如何实现exclude aar包中的某个jar包

要移除的jar包不在aar包中的classes.jar中

直接把aar包里的Jar打包的时候给去掉,就像下面这这样。注意,要使用exclude module这种方式,直接使用exclude group方式没有效果。exclude group的方法适用于exclude JAR包中的文件。

但是,上面的操作有时候不能生效,尤其是复杂依赖的情况下。我们可能需要在每个间接依赖上都手工进行排除操作,这样就非常麻烦了。

这时候最简单的办法就是移除不需要的jar包,然后重新打包了。

或者要移除的jar包在aar包中的classes.jar中

这个时候,使用exclude方法已经不能生效了。你可以使用下面的通用方法

解压aar文件到tmpDir目录下

找到classes.jar包,用压缩工具打开,删除目标文件

将tmpDir重新打包成一个新的aar

另外,有人开发了 排除AAR(Jar)包中冗余或者冲突类的gradle脚本 。如果图方便的话,可以直接用这个脚本来排除。

参考链接


Android ViewPager存在界面卡住的BUG

最近开发的项目出现界面莫名其秒的卡住,直到发生ANR异常退出的问题。
问题排查许久,才发现是由于使用的ViewPager导致的。
ViewPager中使用setCurrentItem长距离设置当前显示的位置的时候,比如0->600,600->10001000->500 这样的长距离跳转。会导致函数卡住在

函数中很长时间, 甚至一直不能跳出循环。具体卡住的的循环代码如下:

上述代码中循环体会一直循环到N结束为止。而这个N是通过

赋值的。恰好,我们的代码中返回的是Integer.MAX_VALUE。咨询了同事,当时设置这个数值的目的是为了解决循环滚动展示才设置的。代码是直接抄的 Android无限广告轮播 自定义BannerView / 如何优雅的实现一个可复用的 PagerAdapter

通过Google搜索关键词 BannerAdapter extends PagerAdapter 可以找到类似的代码。

具体的复现BUG的例子代码如下:

完整的项目代码可以点击此处下载 ViewPager / ViewPagerAppCompatV7。项目编译完成之后,多点击几次 Change Size 按钮就可以复现界面长时间卡住的情况。第二个项目是支持appcompat-v7:18.0.0的版本,目的是观察各个版本的代码是否存在不同,结论是,都一样

这个问题目前的解决方法就是保证ViewPager中的数据不要太多,比如底层分页显示,每页不要太多。另外就是不要大距离跳转,否则会有很多问题

如果能把android.support升级到androidx的话,可以试试最新的ViewPager2,最新的ViewPager2是用RecyclerView 实现的,应该不会有以前的问题了。

这个问题,我已经向Google提交了BUG,估计最后的答复也是要升级到androidx

参考链接


Android无限广告轮播 - ViewPager源码分析