java基础

1.java基本类型:byte(8),short(16),int(32),float(32),double(64),long(64),char(16),boolean(不做规定);
2.装箱和拆箱:是指基本类型和对应的包装类型的转换,int转成Integer叫装箱,Integer转成int叫拆箱;
3.java中的参数,是以值的形式传入方法的,如果参数是基本类型,传的是基本类型的值,如果是其他非基本类型,传递的是指针(也是具体值);
4.重写equals方法时, 也要重写hashCode方法,这是为了保证两个等价的对象,hash值也要相等,以便使用hashMap时不出错;
5.泛型,只在编译期有效,编译过程中,正确校验泛型结果后,会将泛型的相关信息擦去,叫泛型擦除;
6.面向对象三大特性:封装、继承、多态;封装隐藏对象的属性和实现细节,仅对外公开接口;继承实现了代码的复用;多态是指相同的类,调用其相同的方法,表现出不同的行为,是通过类的继承,重写,向上转型来实现的;
7.JVM运行时数据区域:虚拟机栈、本地方法栈、堆、程序计数器、方法区;
8.判断一个对象是否可以回收:引用计数法,可达性分析;
9.可达性分析算法中的GC Roots有:虚拟机栈中局部变量引用的对象、本地方法栈中JNI引用的对象、方法区中类静态属性引用的对象、方法区中的常量引用的对象;
10.引用类型:强引用、软引用(GC且内存不够时回收)、弱引用(GC时就回收)、虚引用;
11.垃圾收集算法:标记清除、标记整理、复制、分代收集;
12.JVM的classLoader有三大类:BootstrapClassLoader启动类加载器、ExtensionClassLoader扩展类加载器、ApplicationClassLoader应用类加载器;
13.Android中的classLoader:PathClassLoader、DexClassLoader、BaseDexClassLoader、BootClassLoader;
14.双亲委派:当类加载器需要加载类的时候,先判断是否已经加载,如果没有加载,将加载请求转发给父类加载器,只有当父类加载器不能加载时,才尝试自己加载;
15.并发三特性:原子性、可见性、有序性。原子性是指一个或多个操作,要么全部执行,过程不被打断,要么全部不执行;可见性指当一个线程修改类共享变量的值,其他线程能够看到修改的值;有序性指程序执行的顺序按照代码的先后顺序执行; synchronized关键字可以保证三性,volatile可以保证可见性和有序性,常用做修饰状态标记量;
16.HasnMap源码,数组+链表+红黑树,动态扩容;
17.

android基础

1.Activity生命周期:onCreate、onStart、onResume、onPause、onStop、onDestroy、onRestart;

2.Activity启动模式:standard、singleTop、singleTask、singleInstance;
standard,默认启动模式,创建新的实例,入栈顶;
singleTop,先检查该activity是否在栈顶存在,如果存在就直接使用,生命周期onNewIntent,不存在就创建并入栈顶;
singleTask,检查整个任务栈是否存在,存在就将该activity上的所有activity出栈,使之成为栈顶;
singleInstance,创建一个独立的任务栈,只放这一个activity;
3.事件分发:从Activity开始,然后分发到ViewGroup,先判断是否拦截,不拦截就分发到View,如果View不处理,返回给ViewGroup,ViewGroup不处理,再返回给Activity;
伪代码:

    //Activity
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (ViewGroup.dispatchTouchEvent(event)) {
            return true;
        }
        return Activity.onTouchEvent(event);
    }

    public boolean onTouchEvent(MotionEvent event) {

    }

    //ViewGroup
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (ViewGroup.onInterceptTouchEvent(event)) {
            return onTouchEvent(event);
        }
        if (View.dispatchTouchEvent(event)) {
            return true;
        }
        return ViewGroup.onTouchEvent(event);
    }

    public boolean onInterceptTouchEvent(MotionEvent event) {

    }

    public boolean onTouchEvent(MotionEvent event) {

    }

    //View
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (mOnTouchListener != null && mOnTouchListener.onTouch(event)) {
            return true;
        }
        return View.onTouchEvent(event);
    }

    public boolean onTouchEvent(MotionEvent event) {
        //处理 onClick() onLongClick() 等方法
    }

4.View绘制过程:onMeasure、onLayout、onDraw;先测量自己及子view,然后布局,然后绘制;

5.Handler相关机制,发送消息过程,处理消息,同步屏障,IdleHandler;
在Framework层涉及到的类有Handler、Message、Looper、MessageQueue,ThreadLocal;
首先从主线程启动开始,通过Looper的prepare方法,创建一个Looper对象和消息队列对象MessageQueue,然后通过ThreadLocal把Looper对象存起来,ThreadLocal是一个类似于Map的结构,key是当前线程,value是具体对象,这样可以保证在一个线程中只有一个对象数据,然后调用Looper的loop方法不断去从消息队列里面读消息,这里的实现方式是开启一个死循环,然后调用MessageQueue的next方法,如果拿到消息就交给消息的handler处理,是Message的一个属性target,如果没有就等待,此时主线程处于阻塞状态,不占用CPU,一直到有消息来。在MessageQueue中,所有的消息会在发送消息的时候,按照指定的时间先后顺序,放入队列结构中,在next方法中,先取消息队列的头部消息,然后和当前时间比较,如果超过当前时间,可以返还给Looper处理,如果还没有到时间,就调用一个native方法去设置唤醒时间,到达时间后再返回消息给Looper,以上是消息的普通处理逻辑,如果开启了同步屏障,或者设置了IdleHandler,会在此基础上增加一些逻辑。
消息的发送是从Handler开始,创建Handler时需要传Looper对象,默认不传会使用当前线程的Looper,使用ThreadLocal取取的,如果线程没有Looper就会报错。发送消息是使用Handler的post方法或者send方法,这些方法最终都会走到MessageQueue的enqueueMessage方法中,然后根据消息的处理时间放到队列的合适位置。以上是消息的发送过程。
消息处理时提到同步屏障和IdleHandler,同步屏障顾名思义是阻碍同步消息,消息队列的postSyncBarrier()方法开启,removeSyncBarrier()方法关闭。在消息队列的next方法中,如果拿到的队列头部消息的target对象为空,表示开启了同步屏障,那么接下来的所有同步消息都不处理,而是只处理异步消息,系统源码中,ui更新时会用到这个机制。而IdleHandler是一个回调接口,通过消息队列的addidleHandler方法添加实现类,当消息队列空闲时(队列为空,或者队首消息是延时任务时),会回调这个接口。

6.系统启动过程:接通电源后,系统加载BootLoader到内存,并拉起LinuxKernel内核,然后启动第一个用户空间的进程,init进程,在init进程中,启动Zygote进程,开启Socket监听,然后通过fork Zygote进程的方式,启动system_server进程,然后启动Binder线程池,启动AMS,WMS,PMS等系统服务,然后通过AMS启动Launcher进程;
7.app启动过程:点击桌面应用Icon后,通过系统的IMS和WMS服务,把点击事件传给Launcher进程,然后Launcher调用startActivity方法,经过一系列的调用链后,由Instrumenttation通过Binder机制,发送消息到system_server进程,然后由AMS通过socket的方式通知Zygote创建应用进程,进程创建后,先实例化ActivityThread,并执行main函数,创建ApplicationThread,开启主线程消息循环loop,然后调用attach方法进行binder通信,通知system_server进程初始化Application和Activity,然后开始界面的布局和绘制;
8.应用启动优化:1)视觉上的优化,设置闪屏图片主题,可以有效消除应用启动时候的白屏现象;2)代码层面的优化,把Application里面初始化的组件分为三种,必须立即在主线程初始化的,可以延迟在主线程初始化的,以及可以在子线程初始化的,然后根据不同手机初始化需要的时间不同,动态的设置闪屏页的时间,闪屏总时间=组件初始化时间+剩余展示时间;
9.网络优化:1)请求速度优化,自己解析域名后,直接用IP地址(https地址不可以直接使用IP地址);连接复用,避免每次请求都建立连接;数据压缩优化,使用protobuf代替json;2)弱网优化,主动和被动地判断是否是弱网,判断为弱网后,切换到QUIC协议(基于UDP);
10.双token机制,首次登陆时,下发access_token和refresh_token,以及对应的过期时间,请求接口时,先判断access_token是否过期,如果没有,直接使用,如果过期了,判断refresh_token是否过期,如果没有,使用并更新两个token和过期时间,如果过期了,需要重新登录。

网络

1.TCP和UDP,TCP是面向连接的,可靠的流协议,实行顺序控制,重发控制,流量控制,拥塞控制等保证数据的可靠,提升网络利用率;UDP面向报文,是无连接的,尽最大可能交付;
2.TCP三次握手和四次挥手:


3.TCP流量控制,流量控制是为了控制发送方发送速率,保证接收方来得及接收。靠窗口滑动实现,既保证了分组无差错、有序接收,也实现了流量控制。
4.TCP拥塞控制,TCP主要通过4个算法进行拥塞控制:慢开始、拥塞避免、快重传、快恢复。
慢开始与拥塞避免
发送的最初,执行慢开始,令cwnd=1,发送方只能发送一个报文段;每次接收到确认后,将cwnd加倍,然后发送方能发送的报文段数量为2、4、8、16...
需要注意,因为每次cwnd都是加倍的,所以到了后面增长速度非常快,这会导致拥塞的可能性更高。所以设置一个慢开始门限ssthresh,当cwnd>=ssthresh时,进入拥塞避免,每次只将cwnd加1。
快重传与快恢复
在接收方,要求每次接收到报文段都应该对最后一个已收到的有序报文段进行确认。例如收到M1,M2,此时再收到M4,应当发送对M2的确认。
在发送方,如果收到三个重复确认,那么就可以知道下一个报文段丢失,此时执行快重传,立即重传下一个报文段。例如收到三个M2的确认,则认为M3丢失,立即重传M3(快重传)。
这种情况下,因为只是丢失个别报文段,而不是真正的网络拥塞,所以执行快恢复,令ssthresh=cwnd/2, cwnd=ssthresh,注意到此时直接进入拥塞避免。
慢开始和快恢复的快慢指的是cwnd的设定值大小,而不是cwnd的增长速率。慢开始cwnd设定为1,而快重传cwnd设定为ssthresh。

5.HTTP:HTTP是基于TCP/IP协议的应用层协议。它不涉及数据包(packet)传输,主要规定了客户端和服务器之间的通信格式,默认使用80端口。HTTP的方法有:GET(获取资源)、HEAD(获取报文首部)、POST(传输实体主体)、PUT(上传文件)、PATCH(对资源进行部分修改)、DELETE(删除文件)、OPTIONS(查询支持的方法)、CONNECT(要求在与代理服务器通信时建立隧道)、TRACE(追踪路径);
6.HTTPS:HTTP存在以下安全性问题:
1.使用明文进行通信,内容可能会被窃听;
2.不验证通信方 的身份,通信方的身份有可能遭遇伪装;
3.无法证明报文的完整性,报文有可能被篡改。
为了解决以上安全问题,有了HTTPS协议,提供加密处理数据(加密,防窃听)、验证对方身份(认证,防伪装)以及数据完整性保护(防篡改)。
基于两种加密算法的特点,HTTPS采用的加密方式是,利用非对称密钥加密的方式,把对称密钥Secret Key传输给通信方(用对方的公钥加密数据,这样就只能用对方的私钥才能解密数据),然后使用对称密钥加密对数据加密。这样做的目的是,在保证通信安全的前提下,也能保证通信的效率。
7.

Flutter

Kotlin