前言:

大家好呀,我是你们的卑微小凯。春招已经接近尾声啦,各位跳槽找工作的小伙伴有没有收获自己满意的offer呢。

小编最近收纳整合了各一线互联网大厂Android岗的面试真题,由初级到进阶,每题都有详细的解析,让你的面试之路不再迷茫。赶紧收藏吧~

目录:

一、春招总结之计算机网络基础

二、春招总结之JAVA基础

三、春招总结之Android初中级

四、春招总结之Android高级

一、计算机网络基础

1.HTTP与HTTPS有什么区别?

HTTPS是一种通过计算机网络进行安全通信的传输协议。HTTPS经由HTTP进行通信,但利用SSL/TLS来加密数据包。HTTPS开发的主要目的,是提供对网站服务器的身份 认证,保护交换数据的隐私与完整性。

2.从网络加载一个10M的图片,说下注意事项

我们首先获得目标View所需的大小,然后获得图片的大小,最后通过计算屏幕与图片的缩放比,按照缩放比来解析位图

具体步骤如下:

将BitmapFactory.Options的inJustDecodeBounds参数设为true并加载图片

从BitmapFactory.Options中取出图片的原始宽高信息,他们对应于outWidth和outHeight参数

根据采样率的规律并结合目标View的所需大小计算出采样率inSampleSize

将BitmapFactory.Options的inJustDecodeBounds参数设为false,然后重新加载图片

3.TCP的3次握手和四次挥手。为什么连接的时候是三次握手,关闭的时候却是四次握手?

因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

4.谈谈对http缓存的了解。

HTTP的缓存机制也是依赖于请求和响应header里的参数类实现的,最终响应式从缓存中去,还是从服务端重新拉取,HTTP的缓存机制的流程如下所示:

HTTP的缓存可以分为两种:

强制缓存:需要服务端参与判断是否继续使用缓存,当客户端第一次请求数据是,服务端返回了缓存的过期时间(Expires与Cache-Control),没有过期就可以继续使用缓存,否则则不适用,无需再向服务端询问。 对比缓存:需要服务端参与判断是否继续使用缓存,当客户端第一次请求数据时,服务端会将缓存标识(Last-Modified/If-Modified-Since与Etag/If-None-Match)与数据一起返回给客户端,客户端将两者都备份到缓存中 ,再次请求数据时,客户端将上次备份的缓存 标识发送给服务端,服务端根据缓存标识进行判断,如果返回304,则表示通知客户端可以继续使用缓存。 强制缓存优先于对比缓存。

5.如何设计在 UDP 上层保证 UDP 的可靠性传输?

传输层无法保证数据的可靠传输,只能通过应用层来实现了。实现的方式可以参照tcp可靠性传输的方式。如不考虑拥塞处理,可靠UDP的简单设计如下:

  • 1、添加seq/ack机制,确保数据发送到对端
  • 2、添加发送和接收缓冲区,主要是用户超时重传。
  • 3、添加超时重传机制。

6.socket断线重连怎么实现,心跳机制又是怎样实现?

断线重连:正常连接断开客户端会给服务端发送一个fin包,服务端收到fin包后才会知道连接断开。 而断网断电时客户端无法发送fin包给服务端,所以服务端没办法检测到客户端已经短线。 为了缓解这个问题,服务端需要有个心跳逻辑,就是服务端检测到某个客户端多久没发送任何数据过来就认为客户端已经断开, 这需要客户端定时向服务端发送心跳数据维持连接。

心跳机制实现:

长连接的实现:心跳机制,应用层协议大多都有HeartBeat机制,通常是客户端每隔一小段时间向服务器发送一个数据包,通知服务器自己仍然在线。并传输一些可能必要的数据。使用心跳包的典型协议是IM,比如QQ/MSN/飞信等协议

1、在TCP的机制里面,本身是存在有心跳包的机制的,也就是TCP的选项:SO_KEEPALIVE。 系统默认是设置的2小时的心跳频率。但是它检查不到机器断电、网线拔出、防火墙这些断线。 而且逻辑层处理断线可能也不是那么好处理。一般,如果只是用于保活还是可以的。通过使用TCP的KeepAlive机制(修改那个time参数),可以让连接每隔一小段时间就产生一些ack包,以降低被踢掉的风险,当然,这样的代价是额外的网络和CPU负担。

2、应用层心跳机制实现。

7.如何尽快的加载资源(网络优化)?

答案就是能不从网络中加载的资源就不从网络中加载,当我们合理使用缓存,将资源放在浏览器端,这是最快的方式。如果资源必须从网络中加载,则要考虑缩短连接时间,即DNS优化部分;减少响应内容大小,即对内容进行压缩。另一方面,如果加载的资源数比较少的话,也可以快速的响应用户。

8.Cookie的作用是什么?和Session有什么区别

cookie和Session都是用来跟踪浏览器用户身份的会话方式,但两者用户场景不同。

  • Cookie:数据保存在客户端。一些敏感数据不要写入,且最好是加密后,拿到服务端解密
  • Session:数据保存在服务端

9.URI和URL有什么区别

URI(Uniform Resource Identifier) :是同一资源标志符,可以唯一标识一个资源 URL(Uniform Resource Location) :是同一资源定位符,可以提供该资源的路径。它是一种具体的 URI,他是URI的子类。

10.在浏览器中输入url地址 >> 显示主页的过程

1、DNS解析,找到对应的ip地址

2、建立TCP连接

3、发送HTTP请求

4、服务器处理并返回HTTP报文

5、浏览器解析并渲染页面6、连接结束

二、JAVA基础

1.通过静态内部类实现单例模式有哪些优点?
(1).不用 synchronized ,节省时间。

(2).调用 getInstance() 的时候才会创建对象,不调用不创建,节省空间,这有点像传说中的懒汉式。

2.简单工厂、工厂方法、抽象工厂、Builder模式的区别?

简单工厂模式:一个工厂方法创建不同类型的对象。工厂方法模式:一个具体的工厂类负责创建一个具体对象类型。抽象工厂模式:一个具体的工厂类负责创建一系列相关的对象。Builder模式:对象的构建与表示分离,它更注重对象的创建过程。

3.内部类、静态内部类区别、使用场景?

Inner类的实例有Outer的实例的指针(即可以访问Outer的成员)。而StaticInner类没有。
内部类的重要作用在于为多重继承提供支持。
简单理解就是:如果把类比喻成鸡蛋,内部类为蛋黄,外部类是蛋壳。那么静态类相当于熟鸡蛋,就算蛋壳破碎(外部类没有实例化),蛋黄依然完好(内部类可以实例化);而非静态类相当于生鸡蛋,蛋壳破碎(无实例化),蛋黄也会跟着xx(不能实例化)。

4.抽象类、接口 继承实现区别?

包含抽象方法的类称为抽象类,但并不意味着抽象类中只能有抽象方法,它和普通类一样,同样可以拥有成员变量和普通的成员方法。注意,抽象类和普通类的主要有三点区别:
  1)抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实 现该方法),缺省情况下默认为public。
  2)抽象类不能用来创建对象;
  3)如果一个类继承于一个抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽 象方法,则必须将子类也定义为为abstract类。
接口中所有的方法不能有具体的实现,也就是说,接口中的方法必须都是抽象方法。从这里可以隐约看出接口和抽象类的区别,接口是一种极度抽象的类型,它比抽象类更加“抽象”,并且一般情况下不在接口中定义变量。

语法层面上的区别
  1)抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
  2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
  3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
  4)一个类只能继承一个抽象类,而一个类却可以实现多个接口。
设计层面上的区别
1)抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。
2)抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。
接口可以继承接口
抽象类可以实现接口(不需要实现接口中的方法,接口是一种特殊的抽象类)
普通类继承抽象类或实现接口
普通类继承抽象类:必须实现抽象类的所有抽象方法和该抽象类父类的所有方法
普通类实现接口:必须实现接口及其父接口的全部方法

5.集合框架,list,map,set都有哪些具体的实现类,区别都是什么?

Java集合里使用接口来定义功能,是一套完善的继承体系。Iterator是所有集合的总接口,其他所有接口都继承于它,该接口定义了集合的遍历操作,Collection接口继承于Iterator,是集合的次级接口(Map独立存在),定义了集合的一些通用操作。

Java集合的类结构图如下所示:

List:有序、可重复;索引查询速度快;插入、删除伴随数据移动,速度慢;

Set:无序,不可重复;

Map:键值对,键唯一,值多个;

1.List,Set都是继承自Collection接口,Map则不是;

2.List特点:元素有放入顺序,元素可重复;

Set特点:元素无放入顺序,元素不可重复,重复元素会盖掉,(注意:元素虽然无放入顺序,但是元素在set中位置是由该元素的HashCode决定的,其位置其实是固定,加入Set 的Object必须定义equals()方法;

另外list支持for循环,也就是通过下标来遍历,也可以使用迭代器,但是set只能用迭代,因为他无序,无法用下标取得想要的值)。

3.Set和List对比:

Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。

List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。

4.Map适合储存键值对的数据。

6.说说你对Java反射的理解?

答:Java 中的反射首先是能够获取到Java中要反射类的字节码, 获取字节码有三种方法:

1.Class.forName(className)

2.类名.class

3.this.getClass()。

然后将字节码中的方法,变量,构造函数等映射成相应的Method、Filed、Constructor等类,这些类提供了丰富的方法可以被我们所使用。

7.说下java中的线程创建方式,线程池的工作原理。

java中有三种创建线程的方式,或者说四种

1.继承Thread类实现多线程

2.实现Runnable接口

3.实现Callable接口

4.通过线程池

线程池的工作原理:线程池可以减少创建和销毁线程的次数,从而减少系统资源的消耗,当一个任务提交到线程池时

a. 首先判断核心线程池中的线程是否已经满了,如果没满,则创建一个核心线程执行任务,否则进入下一步

b. 判断工作队列是否已满,没有满则加入工作队列,否则执行下一步

c. 判断线程数是否达到了最大值,如果不是,则创建非核心线程执行任务,否则执行饱和策略,默认抛出异常

8. 设计模式(六大基本原则、项目中常用的设计模式、手写单例等)

1.单一职责原则:不要存在多于一个导致类变更的原因。

2.里氏替换原则:所有引用基类的地方必须能透明地使用其子类的对象。

3.依赖倒置原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。

4.接口隔离原则:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。

5.迪米特法则:一个对象应该对其他对象保持最少的了。通俗的说:尽量降低类与类之间的耦合。

6.开闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。

9.简单介绍一下java中的泛型,泛型擦除以及相关的概念,解析与分派?

泛型是Java SE1.5的新特性,泛型的本质是参数化类型,也就是说所操的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。

在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者实际参数类型可以预知的情况下进行的。对于强制类型换错误的情况,编译器可能不提示错误,在运行的时候出现异常,这是一个安全隐患。

泛型的好处是在编译的时候检查类型安全,并且所有的转换都是自动和隐式的,提高代码的重用率。

三、Android初中级

1.什么是ANR 如何避免它?

在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应 用程序无响应(ANR:Application NotResponding)对话框。 用户可以选择让程序继续运行,但是,他们在使用你的 应用程序时,并不希望每次都要处理这个对话框。因此 ,在程序里对响应性能的设计很重要这样,这样系统就不会显 示ANR给用户

2.Activity和Fragment生命周期有哪些?

3.android中进程的优先级?

1. 前台进程:

即与用户正在交互的Activity或者Activity用到的Service等,如果系统内存不足时前台进程是最晚被杀死的

2. 可见进程:

可以是处于暂停状态(onPause)的Activity或者绑定在其上的Service,即被用户可见,但由于失了焦点而不能与用户交互

3. 服务进程:

其中运行着使用startService方法启动的Service,虽然不被用户可见,但是却是用户关心的,例如用户正在非音乐界面听的音乐或者正在非下载页面下载的文件等;当系统要空间运行,前两者进程才会被终止

4. 后台进程:

其中运行着执行onStop方法而停止的程序,但是却不是用户当前关心的,例如后台挂着的QQ,这时的进程系统一旦没了有内存就首先被杀死

5. 空进程:

不包含任何应用程序的进程,这样的进程系统是一般不会让他存在的

4.Jar和Aar的区别

Jar包里面只有代码,aar里面不光有代码还包括资源文件,比如 drawable 文件,xml资源文件。对于一些不常变动的 Android Library,我们可以直接引用 aar,加快编译速度。

5.更新UI的方式

Activity.runOnUiThread(Runnable)View.post(Runnable),View.postDelay(Runnable, long)(可以理解为在当前操作视图UI线程添加队列)HandlerAsyncTaskRxjavaLiveData

6.Asset目录与res目录的区别?

assets:不会在 R 文件中生成相应标记,存放到这里的资源在打包时会打包到程序安装包中。(通过 AssetManager 类访问这些文件)

res:会在 R 文件中生成 id 标记,资源在打包时如果使用到则打包到安装包中,未用到不会打入安装包中。

res/anim:存放动画资源。

res/raw:和 asset 下文件一样,打包时直接打入程序安装包中(会映射到 R 文件中)。

7.Handler机制

Android消息循环流程图如下所示:

主要涉及的角色如下所示:

message:消息。MessageQueue:消息队列,负责消息的存储与管理,负责管理由 Handler 发送过来的 Message。读取会自动删除消息,单链表维护,插入和删除上有优势。在其next()方法中会无限循环,不断判断是否有消息,有就返回这条消息并移除。Looper:消息循环器,负责关联线程以及消息的分发,在该线程下从 MessageQueue获取 Message,分发给Handler,Looper创建的时候会创建一个 MessageQueue,调用loop()方法的时候消息循环开始,其中会不断调用messageQueue的next()方法,当有消息就处理,否则阻塞在messageQueue的next()方法中。当Looper的quit()被调用的时候会调用messageQueue的quit(),此时next()会返回null,然后loop()方法也就跟着退出。Handler:消息处理器,负责发送并处理消息,面向开发者,提供 API,并隐藏背后实现的细节。

整个消息的循环流程还是比较清晰的,具体说来:

  • 1、Handler通过sendMessage()发送消息Message到消息队列MessageQueue。
  • 2、Looper通过loop()不断提取触发条件的Message,并将Message交给对应的target handler来处理。
  • 3、target handler调用自身的handleMessage()方法来处理Message。

事实上,在整个消息循环的流程中,并不只有Java层参与,很多重要的工作都是在C++层来完成的。我们来看下这些类的调用关系。

注:虚线表示关联关系,实线表示调用关系。

在这些类中MessageQueue是Java层与C++层维系的桥梁,MessageQueue与Looper相关功能都通过MessageQueue的Native方法来完成,而其他虚线连接的类只有关联关系,并没有直接调用的关系,它们发生关联的桥梁是MessageQueue。

四、Android高级

1.APP启动优化是怎么做的?
分析现状、确认问题

针对性优化(先概括,引导其深入)长期保持优化效果

在某一个版本之后呢,我们会发现这个启动速度变得特别慢,同时用户给我们的反馈也越来越多,所以,我们开始考虑对应用的启动速度来进行优化。然后,我们就对启动的代码进行了代码层面的梳理,我们发现应用的启动流程已经非常复杂,接着,我们通过一系列的工具来确认是否在主线程中执行了太多的耗时操作。

我们经过了细查代码之后,发现应用主线程中的任务太多,我们就想了一个方案去针对性地解决,也就是进行异步初始化。(引导=>第2题) 然后,我们还发现了另外一个问题,也可以进行针对性的优化,就是在我们的初始化代码当中有些的优先级并不是那么高,它可以不放在Application的onCreate中执行,而完全可以放在之后延迟执行的,因为我们对这些代码进行了延迟初始化,最后,我们还结合了idealHandler做了一个更优的延迟初始化的方案,利用它可以在主线程的空闲时间进行初始化,以减少启动耗时导致的卡顿现象。做完这些之后,我们的启动速度就变得很快了。

2.版本迭代导致的启动变慢有好的解决方式吗?
这种问题其实我们之前也遇到过,这的确非常难以解决。但是,我们后面对此进行了反复的思考与尝试,终于找到了一个比较好的解决方式。

首先,我们使用了启动器去管理每一个初始化任务,并且启动器中每一个任务的执行都是被其自动进行分配的,也就是说这些自动分配的task我们会尽量保证它会平均分配在我们每一个线程当中的,这和我们普通的异步是不一样的,它可以很好地缓解我们应用的启动变慢。

其次,我们还结合了CI,比如说,我们现在限制了一些类,如Application,如果有人修改了它,我们不会让这部分代码合并到主干分支或者是修改之后会有一些内部的工具如邮件的形式发送到我,然后,我就会和他确认他加的这些代码到底是耗时多少,能否异步初始化,不能异步的话就考虑延迟初始化,如果初始化时间太长,则可以考虑是否能进行懒加载,等用到的时候再去使用等等。

然后,我们会将问题尽可能地暴露在上线之前。同时,我们真正已经到了线上的一个环境下时,我们进行了监控的一个完善,我们不仅是监控了App的整个的启动时间,同时呢,我们也将每一个生命周期都进行了一个监控。比如说Application的onCreate与onAttachBaseContext方法的耗时,以及这两个生命周期之间间隔的时间,我们都进行了一个监控,如果说下一次我们发现了这个启动速度变慢了,我们就可以去查找到底是哪一个环节变慢了,我们会和以前的版本进行对比,对比完成之后呢,我们就可以来找这一段新加的代码。

3.你们内存优化项目的过程是怎么做的?

1、分析现状、确认问题

我们发现我们的APP在内存方面可能存在很大的问题,第一方面的原因是我们的线上的OOM率比较高。第二点呢,我们经常会看到在我们的Android Studio的Profiler工具中内存的抖动比较频繁。这是我一个初步的现状,然后在我们知道了这个初步的现状之后,进行了问题的确认,我们经过一系列的调研以及深入研究,我们最终发现我们的项目中存在以下几点大问题,比如说:内存抖动、内存溢出、内存泄漏,还有我们的Bitmap使用非常粗犷。

2、针对性优化

比如内存抖动的解决 -> Memory Profiler工具的使用(呈现了锯齿张图形) -> 分析到具体代码存在的问题(频繁被调用的方法中出现了日志字符串的拼接),也可以说说内存泄漏或内存溢出的解决。

3、效率提升

为了不增加业务同学的工作量,我们使用了一些工具类或ARTHook这样的大图检测方案,没有任何的侵入性,同时,我们将这些技术教给了大家,然后让大家一起进行工作效率上的提升。

我们对内存优化工具Memory Profiler、MAT的使用比较熟悉,因此针对一系列不同问题的情况,我们写了一系列解决方案的文档,分享给大家。这样,我们整个团队成员的内存优化意识就变强了。

4.如何避免内存抖动?(代码注意事项)

内存抖动是由于短时间内有大量对象进出新生区导致的,它伴随着频繁的GC,gc会大量占用ui线程和cpu资源,会导致app整体卡顿。

避免发生内存抖动的几点建议:

  • 尽量避免在循环体内创建对象,应该把对象创建移到循环体外。
  • 注意自定义View的onDraw()方法会被频繁调用,所以在这里面不应该频繁的创建对象。
  • 当需要大量使用Bitmap的时候,试着把它们缓存在数组或容器中实现复用。
  • 对于能够复用的对象,同理可以使用对象池将它们缓存起来。

5.你在做布局优化的过程中用到了哪些工具?
我在做布局优化的过程中,用到了很多的工具,但是每一个工具都有它不同的使用场景,不同的场景应该使用不同的工具。下面我从线上和线下两个角度来进行分析。

比如说,我要统计线上的FPS,我使用的就是Choreographer这个类,它具有以下特性:

  • 1、能够获取整体的帧率。
  • 2、能够带到线上使用。
  • 3、它获取的帧率几乎是实时的,能够满足我们的需求。

同时,在线下,如果要去优化布局加载带来的时间消耗,那就需要检测每一个布局的耗时,对此我使用的是AOP的方式,它没有侵入性,同时也不需要别的开发同学进行接入,就可以方便地获取每一个布局加载的耗时。如果还要更细粒度地去检测每一个控件的加载耗时,那么就需要使用LayoutInflaterCompat.setFactory2这个方法去进行Hook。

此外,我还使用了LayoutInspector和Systrace这两个工具,Systrace可以很方便地看到每帧的具体耗时以及这一帧在布局当中它真正做了什么。而LayoutInspector可以很方便地看到每一个界面的布局层级,帮助我们对层级进行优化。

6.你是怎么样自动化的获取卡顿信息?

我们的思路是来自于Android的消息处理机制,主线程执行任何代码它都会走到Looper.loop方法当中,而这个函数当中有一个mLogging对象,它会在每个message处理前后都会被调用,而主线程发生了卡顿,那就一定会在dispatchMessage方法中执行了耗时的代码,那我们在这个message执行之前呢,我们可以在子线程当中去postDelayed一个任务,这个Delayed的时间就是我们设定的阈值,如果主线程的messaege在这个阈值之内完成了,那就取消掉这个子线程当中的任务,如果主线程的message在阈值之内没有被完成,那子线程当中的任务就会被执行,它会获取到当前主线程执行的一个堆栈,那我们就可以知道哪里发生了卡顿。

经过实践,我们发现这种方案获取的堆栈信息它不一定是准确的,因为获取到的堆栈信息它很可能是主线程最终执行的一个位置,而真正耗时的地方其实已经执行完成了,于是呢,我们就对这个方案做了一些优化,我们采取了高频采集的方案,也就是在一个周期内我们会多次采集主线程的堆栈信息,如果发生了卡顿,那我们就将这些卡顿信息压缩之后上报给APM后台,然后找出重复的堆栈信息,这些重复发生的堆栈大概率就是卡顿发生的一个位置,这样就提高了获取卡顿信息的一个准确性。

7.如何优化自定义View

为了加速你的view,对于频繁调用的方法,需要尽量减少不必要的代码。先从onDraw开始,需要特别注意不应该在这里做内存分配的事情,因为它会导致GC,从而导致卡顿。在初始化或者动画间隙期间做分配内存的动作。不要在动画正在执行的时候做内存分配的事情。

你还需要尽可能的减少onDraw被调用的次数,大多数时候导致onDraw都是因为调用了invalidate().因此请尽量减少调用invaildate()的次数。如果可能的话,尽量调用含有4个参数的invalidate()方法而不是没有参数的invalidate()。没有参数的invalidate会强制重绘整个view。

另外一个非常耗时的操作是请求layout。任何时候执行requestLayout(),会使得Android UI系统去遍历整个View的层级来计算出每一个view的大小。如果找到有冲突的值,它会需要重新计算好几次。另外需要尽量保持View的层级是扁平化的,这样对提高效率很有帮助。

如果你有一个复杂的UI,你应该考虑写一个自定义的ViewGroup来执行他的layout操作。与内置的view不同,自定义的view可以使得程序仅仅测量这一部分,这避免了遍历整个view的层级结构来计算大小。

8.View的事件分发机制?滑动冲突怎么解决?

了解Activity的构成

一个Activity包含了一个Window对象,这个对象是由PhoneWindow来实现的。PhoneWindow将DecorView作为整个应用窗口的根View,而这个DecorView又将屏幕划分为两个区域:一个是TitleView,另一个是ContentView,而我们平时所写的就是展示在ContentView中的。

触摸事件的类型

触摸事件对应的是MotionEvent类,事件的类型主要有如下三种:

  • ACTION_DOWN
  • ACTION_MOVE(移动的距离超过一定的阈值会被判定为ACTION_MOVE操作)
  • ACTION_UP

View事件分发本质就是对MotionEvent事件分发的过程。即当一个MotionEvent发生后,系统将这个点击事件传递到一个具体的View上。

事件分发流程

事件分发过程由三个方法共同完成:

dispatchTouchEvent:方法返回值为true表示事件被当前视图消费掉;返回为super.dispatchTouchEvent表示继续分发该事件,返回为false表示交给父类的onTouchEvent处理。

onInterceptTouchEvent:方法返回值为true表示拦截这个事件并交由自身的onTouchEvent方法进行消费;返回false表示不拦截,需要继续传递给子视图。如果return super.onInterceptTouchEvent(ev), 事件拦截分两种情况:  

  • 1.如果该View存在子View且点击到了该子View, 则不拦截, 继续分发 给子View 处理, 此时相当于return false。
  • 2.如果该View没有子View或者有子View但是没有点击中子View(此时ViewGroup 相当于普通View), 则交由该View的onTouchEvent响应,此时相当于return true。

注意:一般的LinearLayout、 RelativeLayout、FrameLayout等ViewGroup默认不拦截, 而 ScrollView、ListView等ViewGroup则可能拦截,得看具体情况。

onTouchEvent:方法返回值为true表示当前视图可以处理对应的事件;返回值为false表示当前视图不处理这个事件,它会被传递给父视图的onTouchEvent方法进行处理。如果return super.onTouchEvent(ev),事件处理分为两种情况:

  • 1.如果该View是clickable或者longclickable的,则会返回true, 表示消费 了该事件, 与返回true一样;
  • 2.如果该View不是clickable或者longclickable的,则会返回false, 表示不 消费该事件,将会向上传递,与返回false一样。

注意:在Android系统中,拥有事件传递处理能力的类有以下三种:

  • Activity:拥有分发和消费两个方法。
  • ViewGroup:拥有分发、拦截和消费三个方法。
  • View:拥有分发、消费两个方法。

9.Android里的内存缓存和磁盘缓存是怎么实现的。

内存缓存基于LruCache实现,磁盘缓存基于DiskLruCache实现。这两个类都基于Lru算法和LinkedHashMap来实现。

LRU算法可以用一句话来描述,如下所示:

LRU是Least Recently Used的缩写,最近最少使用算法,从它的名字就可以看出,它的核心原则是如果一个数据在最近一段时间没有使用到,那么它在将来被访问到的可能性也很小,则这类数据项会被优先淘汰掉。

10.依赖注入框架:ButterKnife实现原理

ButterKnife对性能的影响很小,因为没有使用使用反射,而是使用的Annotation Processing Tool(APT),注解处理器,javac中用于编译时扫描和解析Java注解的工具。在编译阶段执行的,它的原理就是读入Java源代码,解析注解,然后生成新的Java代码。新生成的Java代码最后被编译成Java字节码,注解解析器不能改变读入的Java类,比如不能加入或删除Java方法。

文末

本文参考:jsonchao

今天的面试分享就到这里,整理不易,如果对您有帮助,请关注转发支持一下!

modbus报文解析实例_万字长文!春招面试总结,鹅厂T3Android高频面试真题+解析...相关推荐

  1. shell编程1到10求和_重磅|郑州市第四届中小学创意编程暨智能设计大赛初中组真题解析(下)...

    温馨提示 : 图片点击可放大噢! 判断题01 考察点:变量 解析:答案是A,正确. 新建变量时,勾选仅适用于当前角色是指在本角色内定义的变量,只在本角色程序范围内使用有效:勾选适用与所有角色是指此变量 ...

  2. 历届蓝桥杯青少年Scratch编程选拔赛 STEMA评测比赛真题解析【持续更新 已更新至49题】

    历届蓝桥杯scratch选拔赛真题 第十届.十一届.十二届.十三届蓝桥杯选拔赛STEMA比赛真题解析 选拔赛真题49-购物程序 [蓝桥杯选拔赛真题48]Scratch购物程序 少儿编程scratch蓝 ...

  3. 青少年编程 中国电子学会scratch等级考试二级历年真题解析【持续更新 已更新至2023年3月】

    中国电子学会scratch等级考试二级历年真题解析 一.考级知识点分析 Scratch二级知识点思维导图 二.Scratch二级历年真题讲解(16套) 2023年3月Scratch二级真题 选择题真题 ...

  4. 历届蓝桥杯Scratch编程国赛 初级 中级 青少年编程比赛国赛真题解析【持续更新 已更新至27题】

    历届蓝桥杯国赛真题 第十三界.十二届.十一届等历届青少年蓝桥杯Scratch编程比赛国赛真题解析 国赛真题01-河马带球[试看] [蓝桥杯国赛真题01]Scratch河马带球 少儿编程蓝桥杯Scrat ...

  5. 历届蓝桥杯Scratch编程省赛 初级 中级 青少年编程比赛省赛真题解析【持续更新 已更新至35题】

    历届蓝桥杯scratch省赛真题 历年蓝桥杯Scratch编程比赛省赛真题详细解析 省赛真题35-水面倒影 [蓝桥杯省赛真题35]Scratch水面倒影 少儿编程scratch编程蓝桥杯省赛真题讲解_ ...

  6. 中国电子学会scratch等级考试三级历年真题解析【持续更新 已更新至2022年9月】

    中国电子学会scratch等级考试三级历年真题解析 一.考级知识点分析 Scratch三级知识点思维导图 二.Scratch三级历年真题讲解(12套) 2022年9月Scratch三级真题 选择题真题 ...

  7. 历届蓝桥杯青少年编程选拔赛 科技素养题真题讲解 STEMA评测比赛真题解析【持续更新 已更新至18套】

    信息素养(科技素养)的重要性 教育部等多个部门多次发文强调中小学生信息素养的重要性,而且已经纳入到新课标里面:要提升学生信息素养.各地要指导和推动中小学按照国家课程方案和课程标准开齐开足开好信息技术课 ...

  8. 2022年4月蓝桥杯软件类省赛:真题+解析

    文章目录 试题 A 试题 B 试题 C 试题 D 试题 E 试题 F 试题 G 试题 H 试题 I 试题 J 相关文章: 2021年4月蓝桥杯(软件类)省赛:真题+解析 2020年10月蓝桥杯(软件类 ...

  9. 少儿编程 中国电子学会scratch等级考试一级历年真题解析【已更新至2023年3月 持续更新】

    中国电子学会scratch等级考试一级历年真题解析 一.考级知识点分析 Scratch一级知识点思维导图 二.Scratch一级历年真题讲解(17套) 2020年5月选择题真题解析[试读]:电子学会图 ...

最新文章

  1. 了解TCP的三次握手和四次挥手
  2. oracle ora01732,一天一小步_2008.5.02: ora-01732错误
  3. lisp文字上标源码_创建文本/标注样式源码 - AutoLISP/Visual LISP 编程技术 - CAD论坛 - 明经CAD社区 - Powered by Discuz!...
  4. 用这10个小技巧加速Python编程
  5. MTK 驱动(4)---MTK Android Driver知识大全
  6. java jstat结果分析_JVM调优总结 + jstat 分析
  7. oracle批量更新数据从另一表_全市场期货数据的批量下载和更新
  8. 矩池云上关于conda的一些使用技巧
  9. ASP 中用Ctrl+Enter提交表单
  10. matlab 稀疏矩阵 乘法,Matlab 矩阵运算
  11. 基于SSM的校园订餐管理系统
  12. Rufus创建Windows Server UEFI启动盘
  13. SAR 三点回波模拟 正侧视RD算法(经典好用)
  14. 基于高通sdx12平台,简单介绍编译(bitbake)
  15. 【python--程序】printf格式化输出函数
  16. DANN loss/acc振荡
  17. 西安软件园:英特尔移动通信西安有限公司
  18. 虚拟机从光盘启动方法
  19. Tuxera NTFS Mac2022mac写入ntfs移动硬盘插件
  20. 2020年10月-北京-天眼查面试题(已offer)

热门文章

  1. R语言数据类型:Logical、Numeric、Integer、Complex、Character、Vectors、Lists、Matrices、Arrays、Factors、DataFrames
  2. 什么是牛顿法(Newton methods)?什么是拟牛顿法(Quasi Newton methods)?牛顿法和梯度下降法的区别是什么?
  3. 什么是类别不平衡?有哪些解决方案?
  4. 我国计算机通信技术现状及未来的发展趋势,我国计算机通信技术现状及未来的发展趋势...
  5. NCBI中SRA数据库简介
  6. 机器学习 阴性集的选择 —— drug-target interactions (DTIs)
  7. 【转】NG:垂枝桦基因组图谱构建(2+3组装)及重测序分析
  8. 社交媒体分析-恶意内容自动检测相关论文
  9. java怎么自动提示关键词_Eclipse 实现关键字自动补全功能
  10. predictor = dlib.shape_predictor()关键点预测器用法