都是个人的理解, 如有不对, 敬请指正.
HandlerThread, IntentService
HandlerThread 是一个创建了 Looper循环 的Thread, 可以直接获取到其 Looper 提供给外部的 handler 使用, 并且简单封装了两个quit方法.
IntentService 是内部创建了一个 HandlerThread/Handler 的 Service, 每次 startService 时通过 intent 传递数据, 在 onStartCommand 中调用 onStart 通过 handler 发送给了 Thread 执行, 每次执行完毕后会通过 startId 来 stopSelf.
IntentService 是 HandlerThread 的包装层, 适用于比较简单的场景, 如果给 HandlerThread 发送消息的 handler 还需要传递给 persenter 层等情况下, 还是用 HanderThread 更灵活一些.
逆变/协变
逆变/协变是使用泛型通配符时出现的概念, 没有通配符就没有逆变协变之说
逆变: java 里的 <? super Parent>
, kotlin 里的 <in Parent>
, 父类泛型对象可以赋值给子类泛型对象
协变: java 里的 <? extends Parent>
, kotlin 里的 <out Parent>
, 子类泛型对象可以赋值给父类泛型对象
逆变: myClass<Child> = myClass<Parent>;
协变: myClass<Parent> = myClass<Child>;
类里面的泛型使用时 如果是输入类型的话, 需要把T声明为逆变的; 如果是输出类型的话, 就要把T声明为协变的.
注意, 这里与泛型边界要区别开,
- java实现泛型边界:
class AAA<T extends Parent>
, 多重边界class AAA<T extends Father & Mother>
其中Mother必须是接口; - kotlin实现泛型边界:
class AAA<T : Parent>
, 多重边界class AAA<T>() : AAAFather() where T:Father,T:Mother
生命周期
- 在 onCreate 里面 onDestroy 会崩溃. 调用 finish 会直接执行到 onDestroy, 在 onStart 里面 finish 会执行 onStop-onDestroy, 在 onResume 中执行会走完 onPause-onStop-onDestroy.
- activity 和 fragment 完整的生命周期, 来自 https://github.com/xxv/android-lifecycle
kotlin 的 open 和 abstract
open 使类可以被继承, abstract 的功能 = open 的功能 + 可以声明 abstract 方法;
内部类
- java 中 new BaseCallBack(){…} 的用法都是匿名内部类, 其实只有 new BaseCallBack() 的话就会提示了: abstract类不能实例化
非静态内部类(无论是否匿名)会持有外部类的引用
Handler handler = new Handler(); // 这是实例化 Handler handler = new Handler() { // 这是创建了匿名内部类, 然后直接实例化为父类 @Override ... } Handler myHandler = new MyHandler(); // 创建内部类并实例化, 与上面写法是相同的效果, 只不过不是匿名的内部类了 class MyHandler extends Handler { @Override ... } // 与上面是相同的效果, 都是持有外部类实例的引用, 这里可以把externalClass放在弱引用里, 防止内存泄漏 Handler myStaticHandler = new MyStaticHandler(this); static class MyStaticHandler extends Handler{ Class externalClass; MyStaticHandler(Class externalClass){ this.externalClass = externalClass; } @Override ... }
- 静态内部类就类似于单独的类文件了, 不依赖任何类
软引用/弱引用
软引用 SoftReference 只有在内存不足时才会回收(Android3.1以后推荐使用LruCache), 弱引用 WeakReference 在gc后就会被回收.
声明静态内部类handler/再利用弱引用 可以解决Activity内的handler内存泄漏问题.
public class MyActivity extends Activity {
private MyHandler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new MyHandler(this);
}
@Override
protected void onDestroy() {
mHandler.removeCallbacksAndMessages(null);
super.onDestroy();
}
static class MyHandler extends Handler {
private WeakReference<MyActivity> mOuter;
public MyHandler(MyActivity activity) {
mOuter = new WeakReference<MyActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
MyActivity outer = mOuter.get();
if (outer != null) {
// Do something with outer as your wish.
}
}
}
}
RxJava的merge/zip/flatmap
- Retrofit+RxJava使用中, 可以使用zip操作符合并多个请求, 并在所有的请求全部成功后一起回调, 可以把所有的repsonse放在一个ArrayList里处理, 其中response顺序与zip传入的Observable顺序是一致的;
- merge是各自回调各自的, 不会互相等待, 要求回调的类型均一致;
- flatmap实现多个请求的链式调用, 即一个完成后再开始另一个;
T和?的区别
其实除了都不能指定具体类型之外, 这两个没啥一样的. T是泛型的一种, 一般用来指Type, 另外常用的还有:
1. K(Key);
2. V(Value);
3. E(Enum).
泛型用来指定特定的一种类型, 而?作为通配符可以代指多种类型, 一般有三种用法:
1. 单独的?: 用来指所有类型;
2. ? extends T: 指所有T的子类类型;
3. ? super T: 指所有T的父类;
Https的支持
关于 OkHttp 和 WebView 对 https 的支持简单说有两种:
1. 全部信任: 这种方式可以支持任意 host 里的接口请求, WebView 会直接忽略 https 的不安全提醒. 这种方式会导致app在上架 GooglePlay 的时候被拒绝.
2. 信任特定的证书: 推荐这种方式, 因为接口无需访问其他的服务器, 仅为自己服务器添加证书支持即可.
两种处理方式的参考: 信任特定证书以及双向证书验证 , 全部信任
Parcelable 和 Serializable 的区别
Serializable基于反射, 效率差且内存开销大, 建议使用Parcelable.
在kotlin中可以使用 @Parcelize 注解避免实现大量 Parcelable 方法(当前为实验功能). 注意, 需要在 app 的 build.gradle 中添加
androidExtensions {
experimental = true
}
@Parcelize
data class QYColumnResponse(
var appVersion: String = "",
var contentList: List<QYColumn> = ArrayList(),
var msg: String = "",
var status: String = ""
) : Parcelable
单例和静态类的区别
- 单例是类, 拥有 封装,继承,多态 等面向对象的特性, 对于较为复杂的逻辑更加适合; 静态类是方法集合, 相对独立的方法用静态类会更方便;
- 如果需要资源释放时, 单例会更加方便;
Android系统架构
Andorid系统分为四层, 每一层均封装底层方法, 并向上暴漏接口.
每一层都有Binder的参与.
1. Linux Kernel 内核层, 处理底层的IO口/硬件驱动等;
2. Native中间层, 使用C/C++实现;
3. Framework应用程序框架, 提供各类 ServiceManager, Content Providers等;
4. Application应用层.
内存泄漏
本质是某对象已经不会再使用了, 但是jvm无法释放的情况, 主要原因有两个:
1. 被其他对象强引用;
2. 资源没有关闭;
常见的有以下几种情况:
1. Handler/Thread在Activity/Fragment等界面中创建非静态内部类, 在界面销毁后没有释放;
2. 静态 Context 类;
3. 单例持有 Activity 对象;
4. 某些资源未关闭, 例如: BraodcastReceiver, ContentObserver, File, Cursor, Stream, Bitmap等;
ANR
应用程序未响应, 主要有三种情况
1. KeyDispatchTimeout(5秒): 主要情况, 触摸或按键响应超时;
2. BroadcastTimeout(10秒): 广播事件接收处理超时, onReceive执行超过10秒时出现;
3. ServiceTimeout(20秒): 服务超时, 不常见;
OOP面向对象
面向对象的三大特性: 封装, 继承, 多态
面向对象设计的六大原则:
1. 单一职责原则;
2. 开放封闭原则: 扩展性开放, 更改性封闭;
3. 里氏替换原则: 子类在任意位置都能替换父类, 除了泛型相关;
4. 依赖倒置原则: 具体依赖抽象, 上层依赖下层, 就是说上层仅依赖于下层的抽象而不是具体实现来编写;
5. 接口隔离原则: 模块之间使用接口隔离, 避免强耦合, 例如MVP的VP间;
6. 迪米特原则, 也叫最少知道原则: 即对与自己相关的类知道的最少;
图片格式
- RGB_565: 2byte, 仅色值, 没有透明度
- ARGB_8888: 4byte
- ARGB_4444: 2byte, 质量较差, 不推荐使用
- ALPHA_8: 1byte, 仅存储位图透明度, 没有色值