突闻公司倒闭噩耗,仿佛是在梦中。。。也庆幸自己没有被抓走。。。
5年老android一枚,目前入职了一家小公司,先度过这个难关,加油。
下面是一些面试中遇到的问题,总结一下,以备来年再战。目标BAT,fighting!
也是时间问题,面试准备不够充分。一共面了7家,拿个4个offer,但是都不是很理想。
其中有两家上市公司都没有通过,感觉挺遗憾的。
也奉劝大家一句,能去大公司尽量去大公司、大平台,对自己以后的发展和提升帮助还是挺大的。
以后有机会出去面面试,真的是对自己技术和能力的查漏补缺。
两家上市公司是
-
茄子快传
聊了2个多小时,最后还是回去等通知,主要是问了一些问题的解决方案。
他们项目是全球化的,所以有想去面试的要充分了解一下android的语言适配、view的
rtl属性。其他就是一些 -
汽车之家
这边问的深度比较大,像是组件化,插件化这些一定要好好掌握。这家还要求掌握RN。其他下面会总结一些。
小插曲
- 最右
入职之后,晚上还抽空去面了下最右,当然希望也是不大,反正现在没有消息,凉凉。
这边主要是先刷一套题,具体题目没仔细记。
有一个是清除 listview 里面的为 3 的所有item。(Iterator的用法)
还有一个是手写 成比例高度的自定义控件。
备注:面试官很nice
慢慢会补充
java基础
看这里
https://blog.csdn.net/u013728021/article/details/103239660
Android方面
1. android中的png和jpg的区别和使用场景
png | jpg | |
---|---|---|
中文名 | 便携式网络图型 | 联合图像专家组 |
原名 | Portable Network Graphics | Joint Photographic Experts Group |
压缩形式 | 无损 | 有损 |
体积大小 | 偏大 | 小 |
通道方式 | 有透明通道 | 无透明通道 |
使用场景及原因 | app包中的图片,使用png格式的(由于android系统对png格式有硬件加速) | 1. 网络上加载的图片,使用jpg格式(图片体积小,节流) 2.背景图、引导页,这种大尺寸的图片,倾向于jpg格式(图片体积小,减小安装包体积) |
具体参考 https://www.zhihu.com/question/29758228
为什么png能实现无损压缩
png采用的是argb压缩形式,每一个像素点都argb都会被精确保留下来。
采用的算法是LZ77(映射方式)和哈夫曼编码(最优编码方式),减小图片的内存大小。
https://juejin.im/post/5c8e4feb6fb9a070aa5ce200
为什么jpg是有损压缩
jpg压缩是根据人眼识别的特点把图像分成Y(亮度)Cb(色度蓝)Cr(色度红)的形式。
由于人眼对亮度要比后面两者感应强烈,所以主要针对Cb和Cr进行压缩处理,减少粒度感,是有损压缩。
https://www.jianshu.com/p/934269064bfb
2. android图像显示的底层原理
CPU它的作用是计算图片的形状和文字的纹体
GPU它的功能是渲染图像的颜色
Display屏幕显示图像
VSync显卡输出频率与屏幕刷新频率同步
过程
首先是CPU计算出图像形状,计算完成CPU会将图像交给GPU渲染出颜色,如果这一切都能够在16ms内完成,那么在下一个VSync出现时,就能显示刚刚渲染出来的那1帧图像了,但是如果CPU和GPU处理1帧图像时间超过16ms,那么这帧图像只能等到第2个VSync出现时才能刷出屏幕,呈现给用户了,这也就意味着用户在32ms内所看到的是同1帧的图像,这就是所谓的掉帧,也就是卡顿了。
从代码层面上来看,到底是哪些因素使得CPU,GPU处理图像时间过长呢?
-
过度重绘,有时候是因为你的UI布局存在大量重叠的部分,还有的时候是因为非必须的重叠背景。例如某个Activity有一个背景,然后里面的Layout又有自己的背景,同时子View又分别有自己的背景。仅仅是通过移除非必须的背景图片,这就能够减少大量的红色Overdraw区域。
-
动画使用次数过多。
通常情况下Android需要将xml布局文件转换成GPU可以识别的绘制对象,而这些绘制对象被存放到DisplayList的数组中,当view第一次绘制的时候DisplayList被创建,view第二次绘制的时候GPU就直接从DisplayList获取绘制对象,省去了Measure,Layout的时间,但是如果我们改变了view的绘制内容那么得重新Measure,layout,DisplayList也会被重新创建,这么看来动画效果是非常消耗性能的。因为它必须经过多次重绘。 -
短时间内创建的对象过多
android的垃圾回收机制是,当heap被占用的空间达到一个阈值,GC就开始回收对象了,GC工作的时候大部分线程是阻塞的,所以如果GC耗时超过16ms那么也会出现失帧卡顿的现象。
3. ViewGroup的层级深度
这里就是一个DFS(深度优先遍历)算法
private int maxDeep(View view) {
//当前的view已经是最底层view了,不能往下累加层数了,返回0,代表view下面只有0层了
if (!(view instanceof ViewGroup)) {
return 0;
}
ViewGroup vp = (ViewGroup) view;
//虽然是viewgroup,但是如果并没有任何子view,那么也已经是最底层view了,不能往下累加层数了,返回0,代表view下面只有0层了
if (vp.getChildCount() == 0) {
return 0;
}
//用来记录最大层数
int max = 0;
//广度遍历view
for (int i = 0; i < vp.getChildCount(); i++) {
//由于vp拥有子view,所以下面还有一层,因为可以+1,来叠加一层,然后再递归几岁算它的子view的层数
int deep = maxDeep(vp.getChildAt(i)) + 1;
//比较哪个大就记录哪个
if (deep > max) {
max = deep;
}
}
return max;
}
4. HTTP连接
HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用。
HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
1)在HTTP 1.0中,客户端的每次请求都要求建立一次单独的连接,在处理完本次请求后,就自动释放连接。
2)在HTTP 1.1中则可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。
由于HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种“短连接”,要保持客户端程序的在线状态,需要不断地向服务器发起连接请求。
通常的做法是即使不需要获得任何数据,客户端也保持每隔一段固定的时间向服务器发送一次“保持连接”的请求,服务器在收到该请求后对客户端进行回复,表明知道客户端“在线”。
若服务器长时间无法收到客户端的请求,则认为客户端“下线”,若客户端长时间无法收到服务器的回复,则认为网络已经断开。
5. http中get和post区别
post | get | |
---|---|---|
参数 | 一般放在form表单中 | 拼接在url上 |
特点 | 一般用来更新服务器资源,不安全且不幂等 | 安全且幂等(一般不会造成服务器资源的改变) |
后期会总结一遍关于http的详细文章。
七层协议
注意:
这里有个变态的面试官为了一个 数据链路层 有什么协议。
OSI中的层 | 功能 | TCP/IP协议族 |
---|---|---|
应用层 | 文件传输,电子邮件,文件服务,虚拟终端 | TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet |
表示层 | 数据格式化,代码转换,数据加密 | 没有协议 |
会话层 | 解除或建立与别的接点的联系 | 没有协议 |
传输层 | 提供端对端的接口 | TCP,UDP |
网络层 | 为数据包选择路由 | IP,ICMP,RIP,OSPF,BGP,IGMP |
数据链路层 | 传输有地址的帧以及错误检测功能 | SLIP,CSLIP,PPP,ARP,RARP,MTU |
物理层 | 以二进制数据形式在物理媒体上传输数据 | ISO2110,IEEE802。IEEE802.2 |
什么是socket
套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。
多个TCP连接或多个应用程序进程可能需要通过同一个 TCP协议端口传输数据。
为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。
应用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。
如果一个程序创建了一个socket,并让其监听80端口,其实是向TCP/IP协议栈声明了其对80端口的占有。以后,所有目标是80端口的TCP数据包都会转发给该程序(这里的程序,因为使用的是Socket编程接口,所以首先由Socket层来处理)。
所谓accept函数,其实抽象的是TCP的连接建立过程。accept函数返回的新socket其实指代的是本次创建的连接,而一个连接是包括两部分信息的,一个是源IP和源端口,另一个是宿IP和宿端口。
所以,accept可以产生多个不同的socket,而这些socket里包含的宿IP和宿端口是不变的,变化的只是源IP和源端口。
这样的话,这些socket宿端口就可以都是80,而Socket层还是能根据源/宿对来准确地分辨出IP包和socket的归属关系,从而完成对TCP/IP协议的操作封装!
而同时,放火墙的对IP包的处理规则也是清晰明了,不存在前面设想的种种复杂的情形。
明白socket只是对TCP/IP协议栈操作的抽象,而不是简单的映射关系,这很重要!
TCP的三次握手和四次挥手
https://blog.csdn.net/u013728021/article/details/85261708
WebSocket的简单理解
这个协议是用来帮助客户端进行和服务器进行长链接的协议。
比传统的ajax和long poll性能和处理方式都要好。
具体参考下面链接
https://blog.csdn.net/u013728021/article/details/102727297
android端okhttp完美支持websocket通信,具体可搜索,实现起来也比较简单。
客户端HTTP请求优化实战
这个问题是面试汽车之家android高级开发的时候被问到的一个问题,当时没有答出来,惭愧惭愧
主要针对
- DNS解析问题
- 在业务层面尽量合并接口
- 自动重发机制
- 针对不同的网络状态动态调整timeou
https://blog.csdn.net/u013728021/article/details/102819646
Android的事件分发机制
事件分发主要分三块:分发、拦截、消费;
当我们触摸到屏幕的时候,默认会先走Activity的分发,接着走ViewGroup的分发,然后到ViewGroup的拦截,后面再到View的分发事件,最后会传到View的消费事件,如果View不消费,紧接着回传到ViewGroup的消费事件,如果ViewGroup也不消费,最后回到View的消费事件。整个事件分发构成了一个u型结构,下面总结了分发的细节流程:
在action_down的时候,首先去判断viewgroup的onInterceptTouchEvent是不是拦截了,
如果拦截的话intercepted=true,
就会走handled = dispatchTransformedTouchEvent(ev, canceled, null, TouchTarget.ALL_POINTER_IDS);方法,
此处传的child是null,因此直接走super.dispatchTouchEvent方法,不走child的dispatchTouchEvent方法
如果onInterceptTouchEvent不拦截,那么在action_down的时候,去获取child.dispatchTouchEvent方法,如果返回true,那么mFirstTouchTarget和newTouchTarget都不为空,因此在action_move和action_up的时候会走child的dispatchTouchEvent和ontouchEvent方法
如果child的dispatchTouchEvent方法返回false或者child的ontouchEvent返回false,mFirstTouchTarget和newTouchTarget都为空,因此在action_move和action_up的时候不走child的dispatchTouchEvent和ontouchEvent方法。
如果点击的是viewgroup,那么viewgroup的onInterceptTouchEvent的action_move和action_up都不会被执行。
Activity的事件分发机制
https://blog.csdn.net/u013728021/article/details/102826314
ViewGroup的事件分发机制
https://blog.csdn.net/u013728021/article/details/102831095
View的事件分发机制
https://blog.csdn.net/u013728021/article/details/102826446