Android面试问题汇总(持续更新)

294 阅读15分钟

Java基础

死锁

blog.csdn.net/weixin_3303…

Java平台的理解

Java 本身是一种面向对象的语言,最显著的特性有两个方面,一是所谓的“书写一次,到处运行”(Write once, run anywhere),能够非常容易地获得跨平台能力;另外就是垃圾收集(GC, Garbage Collection),Java 通过垃圾收集器(Garbage Collector)回收分配内存,大部分情况下,程序员不需要自己操心内存的分配和回收。我们日常会接触到 JRE(Java Runtime Environment)或者 JDK(Java Development Kit)。 JRE,也就是 Java 运行环境,包含了 JVM 和 Java 类库,以及一些模块等。而 JDK 可以看作是 JRE 的一个超集,提供了更多工具,比如编译器、各种诊断工具等。对于“Java 是解释执行”这句话,这个说法不太准确。我们开发的 Java 的源代码,首先通过 Javac 编译成为字节码(bytecode),然后,在运行时,通过 Java 虚拟机(JVM)内嵌的解释器将字节码转换成为最终的机器码。但是常见的 JVM,比如我们大多数情况使用的 Oracle JDK 提供的 Hotspot JVM,都提供了 JIT(Just-In-Time)编译器,也就是通常所说的动态编译器,JIT 能够在运行时将热点代码编译成机器码,这种情况下部分热点代码就属于编译执行,而不是解释执行了。

关于JIT: www.jianshu.com/p/ae0d47e77…

JIT(just in time)即时编译器在JVM运行Java字节码时候将其中的热点代码编译成机器码运行,并可以保存下来供下次使用,提升程序运行效率,运行次数越多效率越高。目前统计热点代码有两个方式:

  • 基于采样的热点统计,虚拟机周期性地查看线程的栈顶方法,如果某个方法频繁出现就标记为热点方法,但可能收线程阻塞的干扰
  • 基于统计的热点统计,利用计数器统计每个方法的执行次数,实现比较复杂

多线程内存原理

对象自带的方法

clone、getClass,equal,hashcode,finalize,notify,wait,toString

关于clone blog.csdn.net/zhangjg_blo…

单核cpu是否还存在多线程问题

单核cpu跑多线程程序,线程锁有没有意义? - 忘穿秋裤的回答 - 知乎 www.zhihu.com/question/28…

java多线程在单核CPU上,还是需要volatile synchronized吗? - ETIN的回答 - 知乎 www.zhihu.com/question/63…

hash原理

一、通过hash扰动把高十六位和低十六位进行亦或运算,让hashcode的随机性更高,接着对结果进行取模,JDK1.8开始对把取模换成了通过限定hash表的长度为2的n次幂,然后把结果与hash表长度-1的值进行位与运算,结果与取模相同,但效率更高。

二、解决hash冲突,一直采用链表法,jdk1.8之后采用了链表长度达到8时候转红黑树的方案。为什么是8,因为在装载因子为0.75的时候,链表长度达到8的概率是百万分之一,这个时候转换成红黑树是为了让hashmap在极端情况下抗住大量冲突。而装载因子为什么默认是0.75,根据数学理论,超过0.75时候hash冲突的概率成指数式上升,低于0.75则下降不明显 hashmap在1.7版本时新元素插入链表时候采用的是头插法,在多线程下容易形成环,1.8开始改成了尾插法,避免了这个问题 hashmap在1.7版本时候进行扩容时需要整体rehash,很低效,1.8版本由于控制数组长度为2的次幂,采用的位与运算,每个元素的新位置只取决于高位是1还是0,这样其新位置要么是原位置,要么是原位置+原数组长度,就没必要进行rehash

三、Collections.synchronizeMap()和HashTable都能保证线程安全,但是每个方法都上锁,非常低效。ConcurrentHashMap采用的是低锁粒度+CAS的方式实现锁,不过这些框架都不能完全保证线程安全。

mp.weixin.qq.com/s/8lIcCBGzW…

三个线程循环从1输出到100

blog.csdn.net/u013760665/…

static class MyRunnable implements Runnable {
    private static int count;
    private static ReentrantLock lock = new ReentrantLock();
    private static Condition condition = lock.newCondition();
    private int no;

    public MyRunnable(int no) {
        this.no = no;
    }

    @Override
    public void run() {
        while (true) {
            lock.lock();
            if (count > 100) {
                condition.signalAll();
                lock.unlock();
                break;
            }
            if (count % 3 == no) {
                System.out.println("print num " + count);
                count++;
            } else {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            condition.signalAll();
            lock.unlock();
        }
    }
}

多态底层如何实现的

concurrenthashMap原理

www.jasongj.com/java/concur…

crossoverjie.top/2018/07/23/…

Android和Java的GC过程

cloud.tencent.com/developer/a…

线程池底部如何保证核心线程不卡死

blog.csdn.net/smile_from_…

类加载原理

segmentfault.com/a/119000003…

linkedhashmap

www.jianshu.com/p/b1ab4a170…

反射的原理

www.jianshu.com/p/423e061a4…

有大量后台任务需要执行,但是不能让后台线程占用太多cpu资源,可以采用什么方案?

给主线程配置高优先级,给后台线程配置低优先级,这样保证后台任务在执行。同时主线程能够不卡顿,同时不占用很多cpu资源。

哪些访问是原子性的

cloud.tencent.com/developer/a…

Java内存模型,堆的模型,GC模型和这样设计的原因

juejin.cn/post/689889…

线程池原理,有哪些常见的线程池

juejin.cn/post/684490…

arraymap sparse-array

juejin.cn/post/700104…

hashcode方法

老版本实现为对象地址映射为int值,但是新版本的实现就是一个随机数。

虚拟机

Android Java GC原理

JVM

将所有的新建对象都放入称为年轻代的内存区域,年轻代的特点是对象会很快回收,因此,在年轻代就选择效率较高的复制算法。当一个对象经过几次回收后依然存活,对象就会被放入称为老生代的内存空间。对于新生代适用于复制算法,而对于老年代则采取标记-压缩算法。

Dalvik中GC的问题如下

  • GC时挂起所有线程
  • 大而连续的空间紧张,容易OOM
  • 内存碎片化严重

ART

  • 在ART中标记不需要挂起所有程序的线程:在ART中GC会要求程序在分配空间的时候标记自身的堆栈,这个过程非常短,不需要挂起所有程序的线程
  • 提供 LOS :large object space 专供Bitmap使用,从而提高了GC的管理效率和整体性能
  • ART里有moving collector来压缩活动对象,使得内存空间更加紧凑
  • 分前后台GC算法:前台运用响应性优先采用Mark-Sweep GC,后台应用内存优先采用Mark-Compact GC

Google在ART里对GC做了非常大的优化,从演示的数据里看,内存分配的效率提高了10倍,GC的效率提高了2-3倍。

www.cnblogs.com/cottony/p/1…

cloud.tencent.com/developer/a…

UI

如何计算一个bitmap的大小

www.cnblogs.com/dasusu/p/97…

如何加载大图,如何加载长图片

blog.csdn.net/lmj62356579…

App底层绘制和上屏流程,哪些方法在调用绘制

blog.csdn.net/CrazyMo_/ar…

垃圾文章

xiaojianchen.gitbook.io/performance… blog.csdn.net/u011578734/… cloud.tencent.com/developer/a… cloud.tencent.com/developer/a…

怎么优化卡顿,怎么监测

本地的性能优化文件

Bitmap缓存区大小怎么设定,是多少?

一般我们用LruCache来做缓存
LRUcache

封装了LinkedHashMap

public LruCache(int maxSize) { if (maxSize <= 0) { throw new IllegalArgumentException("maxSize <= 0"); } this.maxSize = maxSize; this.map = new LinkedHashMap<K, V>(0, 0.75f, true); }

maxSize 如果没有重写sizeOf方法,表示元素个数,否则表示cache的最大内存 LinkedHashMap<K, V>(0, 0.75f, true); 三个参数,初始容量,负载因子,遍历顺序,前两个参数实际上是hashmap去用作初始化,初始容量会经过tableSizeFor方法调整为2的幂 每次put方法都会判断当前size是否已经大于maxsize,如果是的话就会删除老元素,直到size小于等于maxsize LinkedHashMap也可以单独用于做lru,重写removeEldestEntry即可

常规使用方案

//获取预设缓存空间大小
//第一种方式:
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
//获取当前硬件条件下应用所占的大致内存大小,单位为M
int memorySize = manager.getMemoryClass();//M
int cacheSize = memorySize/ 8;
//第二种方式(比较常用)
int memorySize = (int) Runtime.getRuntime().maxMemory();//bytes
int cacheSize = memorySize / 8;

LruCache mLruCache = new LruCache<String, Bitmap>(cacheSize) {
@Override protected int sizeOf(String key, Bitmap value) {
//计算一个元素的缓存大小 
return value.getByteCount(); 
    } 
};

juejin.cn/post/684490…

www.jianshu.com/p/b1ab4a170…

在一个viewgeoup上面指定位置画大小固定的view自定义view上有一个bitmap,把bitmap的左上角贴合view的左上角,不缩放画下去,如果超过view部分就裁剪掉在自定义view上有一个图片,图片长度宽度都超过自定义view的大小,要求能够在触摸事件产生时候自动图片,图片不消费事件

recycleView三级缓存原理

juejin.cn/post/700289…

activity window view的关联 popupWindw原理

如何实现一个波纹动画

juejin.cn/post/684490…

setcontentView后面做了什么事情

www.jianshu.com/p/9acdf27aa…

recycle view相比listview的优点

www.jianshu.com/p/cd8244d1c…

如何高效地加载一个大图片

juejin.cn/post/684490…

invalidate和requestlayout区别

www.jianshu.com/p/f9756d277…

如何在界面上滑到播放控件的百分之几时候自动播放

blog.csdn.net/weixin_4564…

blog.csdn.net/confusing_a…

merge为什么能减少一层UI 为什么用LinearLayout不用RelativeLayout

constraintlayout有什么组件

www.jianshu.com/p/193c6a906…

saveInstateState

本地复习资料

不同图片加载库有没有对比他们的优劣

textView surfaceView有没有了解

juejin.cn/post/684490… blog.csdn.net/XAVI_2010/a…

如何在子线程更新UI

juejin.cn/post/684490…

性能优化

leakCanary原理

卡顿优化

如何在一个屏幕上做一个满屏的复杂动画,surfaceView

apk安装 打包流程 如何在一个apk中找到指定的文件

gradle编译、打包原理

如何优化大图

如何控制包体积

sp是不是进程安全的,能不能跨进程读,如果不能该怎么实现

Apk打包过程

LRU缓存

Arraymap

列表卡顿的分析

有没有了解谷歌的xcode开源播放库

Facebook 的rediux框架加快启动速度

屏幕适配做过没,autosize什么时候加载的

网易那边滑动太快是否有什么解决方案

约束布局的性能

开源框架

okhttp retrofit源码,里面有什么设计模式

网络上传时候对基础url的保存,温习retrofit的用法

Jetpack 中livedata 原理

组件化框架的原理

Nanohttpd 实现原理

retrofit原理

abrouter原理

mvp mvvm的区别,为什么选用mvp

路由框架原理

okhttp 原理,线程池地下怎么调度,丢100个任务下去会同时执行吗,怎么保证线程池不会吃掉所有资源,线程池执行完任务后后面干了些什么

缓存机制

leakcanary原理

mat原理

livedata怎么监听生命周期,为什么不自己定义一个观察者模式而用这个

网路

HTTPS 原理

zhuanlan.zhihu.com/p/53374516

https建立的过程

网络基础

请求头有哪些

udp可不可以做成安全的

Http缓存

Http 304啥意思

下载到一半退出后如何重新下载

设计模式

常用的设计模式

观察者模式 适配器模式 工厂模式 单例模式 代理模式 建造者模式
juejin.cn/post/684490…

www.jianshu.com/p/9e1f95e5c…

okhttp retrofit源码,里面有什么设计模式

单例模式,走出同步代码块后其他线程可能把instance设置为空,然后回到该线程时候报了空指针错误

mvvm mvc mvp

m是业务处理和数据管理

v纯展示和相应用户交互

三种模式的区别就在于m和v之间的区别

mvc:view事件传递给c,c交给m做逻辑处理和数据管理,c本质是比较轻的 v注册为m的观察者,m改动会直接通知v。 mvc变体是把m和v解耦了。 缺陷:view和controller很容易耦合,变得很臃肿

mvp:和mvc变体一样,但是三者之间是面相接口编程的,降低耦合,提高可复用性 缺陷:增加了很多接口定义,不利于维护

mvvm:viewmodel通过databinding进行单项和双向绑定,大大减少代码量,viewmodel对view不会有内存泄漏,jetpack的lifecycle关联生命周期,会在页面正常销毁的时候(onDestory),解除观察者,销毁自身。debug问题比较困难,代码复杂性增大,移植性比较差。

mp.weixin.qq.com/s/h2i_17ChO…

mp.weixin.qq.com/s/Kc1826MQ3…

模块化 组件化

Framework

binder原理,client如何找到service

Aidl原理,每一步的细节

parcellable的优越性

Aidl性能瓶颈,多大数据会难以传输

Android进程的main函数入口在哪

同一个线程中为何不能创建多个Looper

可不可以同一个线程中有不同的任务栈

在一个界面按home建退出之后,生命周期变化

activity因为内存不足被杀掉之后,回调用哪些生命周期方法,如果要保存比较大量的数据应该怎么做

handler中post和send区别

启动service的activity挂了,service会发生什么

asynctask实现原理 初始容量大小 能否重用

ANR的原理,系统是怎么监测出来的

mediaplayer的加载文件的流程

两个activity启动时候的生命周期切换

知道无名binder吗,reply如何传递给调用者的,如何寻找到目标binder,只靠包名那不就所有进程都能调用了

handlerThread使用方法,怎么保证handler不为空

能不能通过广播拉起进程

bindservice和startservice的区别

aidl原理 为什么使用aidl

parcelable 和 serializeable 的区别

cas和synchronize的适用场景

Aidl数据流向

Ams启动流程 哪一步开始调用生命周期函数

序列化的实质

其他

数组中去掉重复数字

一百万数据中选出一百个最大的

堆如何删除节点

背包算法

红黑树

设计一个算法,搜索所有的音乐文件

怎么让5个线程执行完了之后执行第六个

手写一个stack

问了Android音视频的主要流程

深度的性能优化

get和post有什么区别

作者:涛叔 链接:www.zhihu.com/question/28… 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

其实可以认为没有区别。只要稍加研读一下 http 协议,你就会发现这个问题可以说根本就不构成一个问题,常见的就是 GET 和 POST。http 1.1 为了表达不同的语义,引入了诸如 DELETE、PATCH 等方法,这种语义不是强制性的。

从字面上看 GET 是查询信息,POST 是提新信息。但你用 POST 方法查询信息也是可以的。例如 gRPC 中所有的请求都是 POST;你用 GET 请求理新信息也是没问题的,君不见多少业务系统的 GET 请求都不幂等。

而且,协议并没有规定 GET 请求不能带 body 的。理论上,任何请求都可以带 body 的。ElasticSearch 查询的时候使用的方法是 GET,但查询 DSL 却是用 body 传输的。另外,uri 中的查询参数也不是 GET 所独有的。POST 请求的 uri 中也可以有参数呀。所以说,GET 和 POST 除了字面语义不同之外,就没有什么区别了。还有一点需要注意,代理一般不会缓存 post 请求的响应内容。

blog.fundebug.com/2019/02/22/…

先下结论

GET 和 POST 方法没有实质区别,只是报文格式不同。

GET 和 POST 只是 HTTP 协议中两种请求方式,而 HTTP 协议是基于 TCP/IP 的应用层协议,无论 GET 还是 POST,用的都是同一个传输层协议,所以在传输上,没有区别。

报文格式上,不带参数时,最大区别就是第一行方法名不同

POST 方法请求报文第一行是这样的 POST /uri HTTP/1.1 \r\n

GET 方法请求报文第一行是这样的 GET /uri HTTP/1.1 \r\n

是的,不带参数时他们的区别就仅仅是报文的前几个字符不同而已

带参数时报文的区别呢? 在约定中,GET 方法的参数应该放在 url 中,POST 方法参数应该放在 body 中

举个例子,如果参数是 name=qiming.c, age=22。

GET 方法简约版报文是这样的

GET /index.php?name=qiming.c&age=22 HTTP/1.1 Host: localhost POST 方法简约版报文是这样的

POST /index.php HTTP/1.1 Host: localhost Content-Type: application/x-www-form-urlencoded

name=qiming.c&age=22 现在我们知道了两种方法本质上是 TCP 连接,没有差别,也就是说,如果我不按规范来也是可以的。我们可以在 URL 上写参数,然后方法使用 POST;也可以在 Body 写参数,然后方法使用 GET。当然,这需要服务端支持。

GET 方法参数写法是固定的吗?

在约定中,我们的参数是写在 ? 后面,用 & 分割。

我们知道,解析报文的过程是通过获取 TCP 数据,用正则等工具从数据中获取 Header 和 Body,从而提取参数。

也就是说,我们可以自己约定参数的写法,只要服务端能够解释出来就行,一种比较流行的写法是 www.example.com/user/name/c…

POST 方法比 GET 方法安全?

按照网上大部分文章的解释,POST 比 GET 安全,因为数据在地址栏上不可见。

然而,从传输的角度来说,他们都是不安全的,因为 HTTP 在网络上是明文传输的,只要在网络节点上捉包,就能完整地获取数据报文。

要想安全传输,就只有加密,也就是 HTTPS。

GET 方法的长度限制是怎么回事?

在网上看到很多关于两者区别的文章都有这一条,提到浏览器地址栏输入的参数是有限的。

首先说明一点,HTTP 协议没有 Body 和 URL 的长度限制,对 URL 限制的大多是浏览器和服务器的原因。

浏览器原因就不说了,服务器是因为处理长 URL 要消耗比较多的资源,为了性能和安全(防止恶意构造长 URL 来攻击)考虑,会给 URL 长度加限制。

POST 方法会产生两个 TCP 数据包?

有些文章中提到,post 会将 header 和 body 分开发送,先发送 header,服务端返回 100 状态码再发送 body。

HTTP 协议中没有明确说明 POST 会产生两个 TCP 数据包,而且实际测试(Chrome)发现,header 和 body 不会分开发送。

所以,header 和 body 分开发送是部分浏览器或框架的请求方法,不属于 post 必然行为。

http演变史

developer.mozilla.org/zh-CN/docs/…

模块化 abrouter 的原理

注解的真实原理,为什么abrouter中用注解就能让组件被注册

servicemanager 和binder通信原理

aidl需要注意什么

mvc mvp mvvm等不同模式的见解

anr crash上报如何做的,有没有做这样的sdk