各类乱七八糟的技术整理

都是个人的理解, 如有不对, 敬请指正.


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

单例和静态类的区别

  1. 单例是类, 拥有 封装,继承,多态 等面向对象的特性, 对于较为复杂的逻辑更加适合; 静态类是方法集合, 相对独立的方法用静态类会更方便;
  2. 如果需要资源释放时, 单例会更加方便;

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. 迪米特原则, 也叫最少知道原则: 即对与自己相关的类知道的最少;


图片格式

  1. RGB_565: 2byte, 仅色值, 没有透明度
  2. ARGB_8888: 4byte
  3. ARGB_4444: 2byte, 质量较差, 不推荐使用
  4. ALPHA_8: 1byte, 仅存储位图透明度, 没有色值

猜你喜欢

转载自blog.csdn.net/j550341130/article/details/79867643