0%

先推荐一下官方的Android源码查看网站:Android Code Search,功能很强大,用起来很方便。

原理分析

之前写过一篇文章:深入理解Android中的SharedPreferences,现在抛开源码,总结成几个关键点:

  1. 只要file name相同,拿到的就是同一个SharedPreferencesImpl对象,内部有缓存机制,首次获取才会创建对象。

  2. 在SharedPreferencesImpl构造方法中,会开启子线程把对应的文件key-value全部加载进内存,加载结束后,mLoaded被设置为true。

  3. 调用getXXX方法时,会阻塞等待直到mLoaded为true,也就是getXXX方法是有可能阻塞UI线程的,另外,调用contains和
    edit等方法也是。

  4. 写数据时,会先拿到一个EditorImpl对象,然后putXXX,这时只是把数据写入到内存中,最后调用commit或者apply方法,才会真正写入文件。

  5. 不管是commit还是apply方法,第一步都是调用commitToMemory方法生成一个MemoryCommitResult对象,注意这里会先处理clear旧的key-value,再处理新添加的key-value,另外value为this或者null都表示需要被remove掉。

  6. 调用commit方法,就会同步执行写入文件的操作,该方法是耗时操作,不能在主线程中调用,该方法最后会返回成功或失败结果。

  7. 调用apply方法,就会把任务放到QueuedWork的队列中,然后在HandlerThread中执行,然后apply方法会立即返回。但如果是Android8.0之前,这里就是放到QueuedWork的一个单线程中执行了。

  8. 最后是写入文件,会先把原有的文件命名为bak备份文件,然后创建新的文件全量写入,写入成功后,把bak备份文件删除掉。

Read more »

Android P非SDK接口限制

1. 三种名单

  • 黑名单:不可使用,否则会抛出异常。

  • 灰名单:如果当前apk的API级别<接口的限制API级别,那么可以用,否则抛出异常。

  • 白名单:受支持的接口,可以使用。

2. 抛出异常

如果使用了黑名单的接口,就会抛出异常,调用getDeclaredField()方法会抛出NoSuchFieldException,调用getDeclaredMethod()方法会抛出NoSuchMethodException。

Read more »

前言

ThreadLocal是JDK中的一个类,很多基础框架和平时开发中都会使用到,因此有必要弄清其内部原理,才能更好地使用它。

使用方法

要弄清原理,还是要先知道如何使用,ThreadLocal用起来是很简单的,一般都是把ThreadLocal定义为static变量,也就是只有一个实例对象,如下:

private static ThreadLocal<Integer> sThreadLocal = new ThreadLocal<Integer>();
Read more »

前言

okhttp是目前很火的网络请求框架,Android4.4开始HttpURLConnection的底层就是采用okhttp实现的,其Github地址:https://github.com/square/okhttp

来自官方说明:

OkHttp is an HTTP client that’s efficient by default:

  • HTTP/2 support allows all requests to the same host to share a socket.
  • Connection pooling reduces request latency (if HTTP/2 isn’t available).
  • Transparent GZIP shrinks download sizes.
  • Response caching avoids the network completely for repeat requests.
Read more »

前言

新建一个AS工程,编译器会自动帮我们创建了Gradle Wrapper相关的文件,目录结构如下:

├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat
Read more »

前言

本文主要介绍Java反射的内部原理,反射慢的原因,如何优化反射。

源码分析

平时开发中反射用得最多的应该是方法调用,下面分析反射调用方法的内部原理,先看getDeclaredMethod方法:

@CallerSensitive
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
    throws NoSuchMethodException, SecurityException {
    checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
    Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
    if (method == null) {
        throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
    }
    return method;
}
Read more »

前言

在项目中,使用多线程是很常见的事情,但是如果处理不当,代码写的不好,就可能会导致线程死锁,对于死锁问题,从发现到定位问题都是比较困难的,如果是线上用户发生了线程死锁,那就是难上加难了,因此最好是项目本身有自己一套线程死锁检测机制,能够自动检测,自动上报,然后我们分析上报日志就可以了。

WatchDog原理

Read more »

前言

当我们执行git init命令,或者clone网上某个代码仓库后,会看到有一个.git目录,git所有版本控制信息就是放在目录里面,下面对这个.git目录进行分析。

.git目录

  • hooks:钩子目录,存放执行指定git命令前或者后触发的脚本,可以看到默认会有几个sample文件,如果要开启某个钩子脚本,就把脚本文件名的后缀simple去掉就可以,这些钩子会在特定的时机被触发执行,比如post-commit在整个提交过程完成后执行,可以用于发送提交通知等,另外也有服务端钩子,在推送前或者后执行,比如post-receive在推送结束后会被执行,可以用于通知打包平台启动打包任务。关于git钩子更详细的信息可以参考:自定义 Git - Git 钩子

  • info:保存git的相关信息

  • logs

    • refs:暂存记录,本地分支记录,远程分支记录

    • HEAD:记录每次的变更操作

Read more »

前言

如果应用耗电量过大,就会消耗用户手机过多的电量,甚至发热,现在一般手机都会有耗电量过大的提醒,当用户看到后,也可能会把你的应用卸载掉,因此需要对其进行优化,让应用的耗电量尽可能小。

检测工具

Battery Historian:https://github.com/google/battery-historian

Read more »

前言

Android中使用SQLite做为数据库,当数据量很大的情况下,就可能会出现性能问题,比如查询速度过慢,更新速度过慢等,因此需要对其进行优化。

优化方法

  • 使用事务

    每次事务都会修改rollback journal文件,因此比较耗时,对于批量操作,应该合并到同一个事务中。

  • 建立索引

    对查询多,更新少的字段建立索引,但索引会占用空间,而且会降低更新速度。

  • 使用SQLiteStatement

    对于循环执行数据库操作,应该在循环外预编译好sql语句得到SQLiteStatement对象,然后循环内bindXXX,而不是直接在循环内调用execSQL方法,这样会导致创建大量的SQLiteStatement临时对象,而且每次都会重新编译sql语句。

  • 缓存getColumnIndex返回结果

    对于循环执行数据库操作,getColumnIndex方法应该放到循环前调用,而不是每次循环都调用一次,虽然该方法的本质是从Map中查找index,但对性能还是有一定的影响的,放在循环前调用会稍微快一些。

  • Cursor优化

    正如微信的WCDB所说,在合适的场景下,直接把Cursor的共享内存缓存去掉,会提高数据查询的速度。

  • 分表、分库

    SQLite的同步锁是表级别的,因此为了避免等待,可以按照具体场景拆分为多个表,或者分库。

  • SQL语句拼接

    不要用+进行连接,用StringBuilder,有循环的最后放到循环外部,不要每次循环都去生成sql语句字符串。

  • SQL语句优化

    适用所有数据库优化,不仅仅只是SQLite,见下部分。

Read more »