RecyclerView中DiffUtil的一些注意事项
节能刷新移动设备屏幕大小有限(不得不说我是顽固的小屏爱好者,大于5.5寸难以接受,时代已经抛弃我了哈哈),列表(List)可以说是一个出现非常高频的交互设计。大多数情况下我们的列表不仅仅是一次性加载本地数据,而要应付来自网络的各种动态内容,可能是增加、删除等操作。
在Android开发中,一个耳熟能详的方法就是 notifyDataSetChanged ,在适配器(Adapter)的设计模式下,每当我们的列表数据发生变更时,就需要调用此方法来更新UI。然而,这个方法并不“节能”,它会同时刷新列表中的所有item,包括那些并没有变化的数据,这样就带来很多计算资源的浪费。要知道,从你的一个 setText 或者 setImageResource 方法调用到最终呈现到屏幕上,软件到硬件,中间经历了非常复杂的过程。基于能省则省的移动开发原则,有没有更好的办法呢?
DiffUtil用起来谷歌确实也考虑到了这个问题,所以不知道在什么时候(暂时没有去查阅)推出了DiffUtil这个解决方案。在RecyclerView的依赖包下面,可以看到,除了DiffUtil,还有异步处理数据等一系列有趣的工具。D ...
MTK设备上DuraSpeed导致Service无法启动的问题
没想到联发科还会改framework,有点小惊讶……
背景问题的起因是我们的系统应用无法调起与其他部门联动的某个Service组件了。查日志发现有这么一行:
11276-2330/system_process D/ActivityManager: bringUpServiceLocked, suppress to start service!
提示内容大概是说Service的启动被禁止了,当时我比较纳闷,难道谷歌又搞了什么幺蛾子?哈哈,而且最奇怪的是只在那一台特定型号的设备上复现问题,其他机型一切正常。这台设备最大的不同就是处理器是MTK的,其他正常机型是高通的。
探查既然日志内容如此明显,问题也比较好查了,我们去看看这行log是在Android源码的哪一行出现的。正好最近谷歌推出了官方的源码检索平台:Android Code Search,可以在线搜索AOSP和AndroidX的代码,简直方便。ActivityManager这个TAG的log有很多地方,我们直接查找 bringUpServiceLocked 方法所在的代码即可。对应的文件路径为:frameworks/ ...
Win10家庭版如何正确关闭自动更新
之所以不更新,是因为你太好用,舍不得你出问题。哈哈哈哈哈哈啊哈哈哈!
背景Windows10还是很漂亮很好用的,大部分同学购买的品牌机也都会预装正版Win10,不过是家庭版的(个人用户一般也不需要专业版,比如我这种装双系统的只把Win10拿来打游戏),然而,家庭版系统要用常规手段是没法彻底关闭自动更新的。微软也非常不给面子,各种给你悄悄打开,当你关机时,你会吃惊地发现“更新并关机”这个选项。下面就介绍一下正确关闭自动更新的方法。
解决找回家庭版的组策略换新电脑以前我也是用的专业版,从来没有自动更新过,印象中就是在设置了组策略后生效的。但众所周知,组策略在家庭版上默认是打不开的,当然这并不代表功能缺失,而是隐藏了。如何找回?1、打开Windows的记事本,输入内容如下:
123456@echo offpushd "%~dp0"dir /b %systemroot%\Windows\servicing\Packages\Microsoft-Windows-GroupPolicy-ClientExtensions-Package~3*.mum >gp.txtdi ...
避免Android定制ROM中的EditText出现pop弹窗
问题可能看到标题的同学一头雾水,这是什么东西,其实类似于你长按文本时出现的复制粘贴pop弹窗。在一些定制ROM中,厂商为了某些方便用户的特殊功能会增加文本输入检测和自定义弹窗,举例:比如在你输入一些邮箱时,会自动弹出这种pop(并不需要你长按),且这个并非系统应用才有的,而是直接影响了所有EditText。对于一些高度定制化UI的应用来说,这个可能影响用户体验。下面给出两种解决办法(都不算特别完美,毕竟卑微的应用层开发者改不了底层实现),大家酌情参考。
解决方法一:要解决问题先思考(合理猜测)一下它的实现原理,很显然它修改了EditText或者TextView源码,在文本输入监听中加入了对邮箱特征的检测,我们可以尝试修改getText方法的返回值,过滤这种特征:
12345678910// 在自定义的EditText中重写getText@Overridepublic Editable getText() { String text = super.getText() != null ? super.getText().toString() : null; if ( ...
为何点击推送通知打不开Activity?Calling startActivity() from outside……
小米推送Android SDK有这么一个耳熟能详的方法:
1234567/** * 接收服务器向客户端发送的通知消息,在用户手动点击通知后触发 */public void onNotificationMessageClicked(Context context, MiPushMessage message) { ... context.startActivity(intent);}
如果在其中手动增加启动Activity的逻辑,会发现,点了没反应。把 startActivity 方法try-catch后,发现这么一个异常:
Calling startActivity() from outside of an Activity context requires theFLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
解读一下就是,说我要是从外面启动本应用的Activity需要传 FLAG_ACTIVITY_NEW_TASK 标识,还特别嘲讽地反问我一句:Is this really what yo ...
源码茶舍之PackageManager获取注册Service数量问题
问题今天有朋友遇到个问题,说bindService失败了,查了几步发现是由于PackageManager获取不到对应的Service组件导致的。具体示例代码如下:
12val serviceInfos = packageManager.getPackageInfo("com.xxx.xxx", PackageManager.GET_SERVICES).servicesLog.d("TEST", Arrays.toString(serviceInfos))
这里我们通过PackageManager获取到对应包名的PackageInfo,最终的serviceInfos是一个数组,包含该应用注册的所有Service组件。但不同时候打印出来的数组长度竟然不同,也就是说某些Service一会儿有一会儿没有,这是为什么呢?
溯源要搞清楚上面的问题,我们就要追本溯源啦!在追踪的过程中我们时刻记得留意一切可能使services数组发生变化的逻辑。
提示:以下Android系统源码均基于Android P。
先看看PackageInfo的源码中对servic ...
Deepin系统add-apt-repository失败的问题
不只是安装software-properties-common那么简单……
问题目前Deepin系统版本为15.11,貌似在15.10时切到了Debain的软件仓库,而不再是Ubuntu了,虽说比较稳定,但还不够新,比如git,版本就没有官方的新。于是我尝试 git官方的办法:
1sudo add-apt-repository ppa:git-core/ppa
报错,提示未找到命令。
解决这个问题在网上搜搜办法,很多回答都是让安装一个包:
1sudo apt-get install software-properties-common
是的,确实解决了 add-apt-repository 命令找不到的问题,但实际add仓库源时,还是会出错,你可能会看到如下内容:
Traceback (most recent call last): File “/usr/bin/add-apt-repository”, line 95, in sp = SoftwareProperties(options=options) Fi ...
Gradle命令编译失败NoClassDefFoundError和VerifyError
问题不知道大家在编译gradle项目的时候习惯直接在Android Studio这种IDE里面还是命令行操作。今天在Deepin系统里面用命令编译:
1./gradlew assembleDebug
直接报错:
Exception in thread “main” java.lang.NoClassDefFoundError: org.gradle.wrapper.BootstrapMainStarter at java.lang.Class.initializeClass(libgcj.so.17) at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)Caused by: java.lang.VerifyError: verification failed at PC 96 in org.gradle.wrapper.BootstrapMainStarter:start(([Ljava.lang.String;Ljava.io.File;)V): incompatible type ...
Deepin标题栏太高的解决办法(自定义高度)
Deepin 15.11已经发布一段时间了,前段时间折腾了一下,把我的Ubuntu换成了Deepin(有兴趣可以看看我的另一篇:Deepin15.11初体验及问题解决),总体感觉非常好。依我个人习惯,目前有两点不是很能接受:
第一就是软件源貌似是debian stable的,所以很多软件版本比较老,比如git版本,远低于官方版本,这个还是有一些解决办法的,具体的我就没去折腾了,Deepin官方主要可能还是考虑兼容性和稳定性吧。
第二就是UI,默认的主题其实还是很好看的,但唯一不能接受的就是标题栏太高而且还不能提供修改的方法。
默认的标题栏在系统的一些界面里还是很好看很契合的,可一旦到了三方软件上,就惨不忍睹了。我量了一下足足占了40像素,又要少看两行代码了哈哈哈!我更希望它只有24像素,就像这样:
解决办法其实不止我一个人,很多用户也在官方issue里吐槽了,所以早就有了解决办法。1、先创建一个目录,如果有就不用了:
1234# 如果你是用的默认的白色主题mkdir -p ~/.local/share/deepin/themes/deepin/light# 如果你用的黑色主题mkd ...
Deepin15.11初体验及问题解决
Deepin发展也有不少年了,最近还和华为的笔记本合作预装。之前我一直都用Ubuntu做日常开发,现在心血来潮也想折腾一下Deepin哈哈,本文主要讲从Ubuntu无痛迁移到Deepin的安装过程、N卡显卡驱动等一系列小坑的解决。权当总结吧!
下载和制作启动盘这个就不讲了哈,直接在官网下就行了,包括启动盘制作工具。http://www.deepin.org/download/
保留数据从Ubuntu迁移到Deepin操作系统先说一下我的Ubuntu分区挂载情况:我单独挂载了/home和/efi,除此之外都分给了/,平时的重要文件都在home里面,这样在装其他Linux时也方便。
进入Deepin的安装分区步骤时:
依然挂载/home到原来的/home上面,且千万不要选择格式化;
然后由于我之前的Ubuntu就是UEFI启动方式,所以同样挂载/efi覆盖原来的,这个可以格式化;
最后剩余空间挂载/,并选择格式化,界面上还会提示你Deepin会安装到这里。
重点: 在填用户名时一定要和之前Ubuntu的不一样,这 ...
Docker安装Ubuntu镜像并保存且修改IP及Mac地址
本文仅作为一个Docker入坑笔记。主要介绍:1、Docker在Linux上的安装配置;2、在Docker容器中安装一个Ubuntu镜像并保存更改;3、以任意IP地址和Mac地址启动刚才安装的Ubuntu镜像。
运行环境简介一下我的环境,方便参考:Linux 4.15.0-64-generic #73~16.04.1-Ubuntu SMP Fri Sep 13 09:56:18 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
Docker安装配置无论何时,都要先找官方文档,对于入门来说,这比任何东西都管用。这里以Ubuntu为例,其他系统类似。起手update源:
1sudo apt-get update
装一些必要的工具(一般来说不是刚装系统的话,都可以略过此步):
123456sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ software-properties-common
添加官方ke ...
OkHttp自定义重试拦截器出现IllegalStateException: cannot make a new request……异常
问题OkHttp自定义重试拦截器常见实现方式:
12345678910111213private static class RetryInterceptor implements Interceptor { @Override public okhttp3.Response intercept(Chain chain) throws IOException { int retryCount = 0; Request request = chain.request(); okhttp3.Response response = chain.proceed(request); while (!response.isSuccessful() && retryCount < RETRY_MAX_COUNT) { retryCount++; response = chain.proceed(request); } ...
Ubuntu安装Source Insight导入Android源码并设置仿IDEA主题Darcula
预览先来张图给大家感受下效果,然后我再慢慢道来过程,保证你避免每一步的坑。
我们要做什么1、由于Source Insight(以下简称SI)是Windows应用,所以不能直接安装在Linux上,于是我们要借助wine,所以第一步会介绍wine的安装过程和坑;2、介绍SI在Linux(以Ubuntu 16.04为例)上的安装,并介绍如何导入免费证书(个人建议大家有条件还是付费支持一下SI这个软件,真的是个好东西,比IDEA看源码实在快太多了,我已经买了最新版4.0,还是挺良心的,一次性付费,239美刀);3、用SI导入AOSP源码并Sync文件建立索引,开头那张截图就是正在Sync,建立完成后就可以快速导航各个方法类引用等等了;4、默认主题太刺眼,怎么办?还是习惯IDEA的风格,没事,我配置都写好了,只用你一键导入并改改字体大小即可!
第一步:安装wine直接命令走起:
1sudo apt-get install wine
过程中终端会显示一个确定页面,按Tab键选中并确定即可,然后再选“是”。一般来说由于依赖问题,上述命令都是不能一次性安装成功的,这时候直接:
1sudo apt-ge ...
Kotlin操作符快速获取爸爸的儿子的狗的名字
NPE(NullPointerException)是最低级且也最容易犯的错,也是最喜欢遇到的Bug因为好解。本文适合Kotlin入门萌新食用,大佬轻喷哈哈哈!
问号N连帮你空处理(?)假如服务端返回一个json嵌套了各种数据,映射成POJO大概是这样:
123456789101112// 此处为简洁省去getter和setterpublic class TestParent { private TestChild child; public class TestChild { private List<TestDog> dogs; public class TestDog { private String name; } }}
然后,你为了知道他爸的儿子的第一条狗叫啥名,你需要这样:
123456789101112if (parent != null) { // 有爹 TestParent.TestChild ch ...
OkHttp拦截器实现禁止一切网络请求
我们在创建OkHttp客户端时,可以添加各种拦截器,这是我见过最有可玩性的库之一:
123456OkHttpClient okHttpClient = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .addInterceptor(new XXXInterceptor()) .addInterceptor(new YYYInterceptor()) .... .build();
设想这么一个场景,用户有一个开关,可以允许或禁止应用内的一切网络请求,如何用拦截器来实现?为了不让大家觉得我又在水贴,直入主题。我们可以通过构造一个404的response来拦截请求:
12345678910111213141516private static class NetworkInterceptor implements Interceptor { @Override public okhttp3.Response interc ...