Android 2020年经典面试题

1.启动优化

什么是逻辑异步?就是用多线程去替代之前单个主线程的工作,尽量保证让onCreate流畅不被堵塞。那么我们该怎么设计呢?设计的思路我们可以参考Gradle,将逻辑Task化。

1.将原本冗余的逻辑代码区分开来,抽象成一个Task

2.确定Task是否必须执行在主线程,是否必须在onCreate中执行完,执行上下是否存在依赖关系

3.设计一个Task分发管理类,负责将所有Task集合后生成一个有向无环图,这点也是参考Gradle的

1.逻辑异步

2.逻辑延迟

3.逻辑懒加载

 

2.怎么在加载大的图片的时候保证不内存溢出

1.压缩图片(图片压缩的 分辨率压缩和质量)

2.改变色彩模式,RGB.565可以有效的减小图片的大小

3.注意回收内存

4.使用Drawable代替bitmap

5.使用decodeStream杜绝decodeResource

public static Bitmap readBitMap(Context context, int resId) {

     BitmapFactory.Options opt = new BitmapFactory.Options();

    opt.inPreferredConfig = Bitmap.Config.ARGB_4444;

    opt.inPurgeable = true;

    opt.inInputShareable = true;

// 获取资源图片

InputStream is = context.getResources().openRawResource(resId);

Bitmap bitmap = BitmapFactory.decodeStream(is, null, opt);

try {

if(is != null)

is.close();

} catch (IOException e) {

e.printStackTrace();

}

return bitmap;

照片压缩,降低采样率

6.巧用BitmapFactroy.Options进行图像高效压缩

网上铺天盖地的都是推荐使用simplesize来进行图像压缩,然而,我却发现一种更节省内存的方法。依然是使用BitmapFactroy.Options,通过设置图片的显示密度来压缩图片,从而达到减小内存占用量的目的。

 

3.内存优化

1.使用性能高的数据结构

2.避免在Android里面使用Enum

3.减小Bitmap对象的内存占用

Bitmap极容易消耗内存,减小创建出来的Bitmap的内存占用可谓是重中之重,通常来说有以下两个措施:

  • inSampleSize:缩放比例,在把图片载入内存之前,我们需要先计算出一个合适的缩放比例,避免不必要的大图载入。
  • decode format:解码格式,选择ARGB_8888/RBG_565/ARGB_4444/ALPHA_8

4.某些场景下,用shape替代图片

有时候会有一些渐变或者描边的UI效果,如果可以用画的就尽量不要直接引用图片资源了,如下所示:

android:angle="0" android:endColor="#ffffff"/>

5.代码混淆&减少不必要的类、类库

6.使用Parcelable进行内存间数据传输

7.内存对象的复用

复用系统自带的资源

Android系统本身内置了很多的资源,比如string、color、drawable、anim、style以及简单layout等,这些资源都可以在应用程序中直接引用。这样做不仅能减小APK的大小,还可以在一定程度上减少内存的开销

8.使用handler.obtainMessage()创建Message对象

不要再用new Message()的方式创建Message对象啦!handler.obtainMessage()内部使用了对象池技术,可以有效帮助我们减少创建Message对象的内存消耗

9.避免对象的内存泄露

WebView造成的内存泄漏

属性动画造成内存泄漏

内存泄漏的检测工具

  • Android Profiler
  • LeakCanary
  • MAT

线程造成内存泄漏

对于线程造成的内存泄漏,也是平时比较常见的,异步任务和Runnable都是一个匿名内部类,因此它们对当前Activity都有一个隐式引用。如果Activity在销毁之前,任务还未完成,

那么将导致Activity的内存资源无法回收,造成内存泄漏。正确的做法还是使用静态内部类的方式,如下:

资源未关闭造成内存泄漏

集合类造成内存泄漏

handler的延时发送消息是怎么实现的

本质上是通过调用handler的sendMessageAtTime,起原理的在消息插入队列的时候,会根据消息插入时的当前时间+需要延时的时间,来算好消息在队列中的位置,loop去取消息的时候,会判断当前时间和该消息的发送时间,如果当前时间大于发送的时间,loop则取出消息并发送,否则让线程进入休息,一段时间,到下次消息需要发送的时候,再触发。

 

问:final 可以修饰类和方法吗?

答:可以修饰class表示该类无法被继承,也可以修饰方法表示该方法无法被重写

问:同步锁对于静态方法锁的对象是什么?

答:class本身

activity启动涉及哪些动作?

obtinMessage的优势,为什么不用new Message?

从整个Messge池中返回一个新的Message实例,在许多情况下使用它,因为它能避免分配新的对象

如果是这样的话,那么通过调用obtainMessage方法获取Message对象就能避免创建对象,从而减少内存的开销了。

 

Android TCP通信 TCP层是介于IP层和应用层的中间层

本质是通过Socket进行通信,服务端创建一个ServiceSocket,客户端创建一个Socket,两者通过Ip和端口进行连接,连接成功后,就酒交给IO流进行通信。

http通信方式

HttpURLConnection和HttpClient,HttpURLConnection多用于发送或接收流式数据,因此比较适合上传/下载文件,HttpClient相对来讲更大更全能,但是速度相对也要慢一点。在此只介绍HttpClient的通信流程:

HTTP的请求方式

1、OPTIONS

返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性

2、HEAD

向服务器索与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以再不必传输整个响应内容的情况下,就可以获取包含在响应小消息头中的元信息。

3、GET

向特定的资源发出请求。注意:GET方法不应当被用于产生“副作用”的操作中,例如在Web Application中,其中一个原因是GET可能会被网络蜘蛛等随意访问。Loadrunner中对应get请求函数:web_link和web_url

4、POST

向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。 Loadrunner中对应POST请求函数:web_submit_data,web_submit_form

5、PUT

向指定资源位置上传其最新内容

6、DELETE

请求服务器删除Request-URL所标识的资源

7、TRACE

回显服务器收到的请求,主要用于测试或诊断

8、CONNECT

HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。

Http是应用层协议,TCP是网络层协议,

我觉得区别从这两个连接的实现方式就可以看出来,HTTP连接需要指明资源的URL,发出请求的应用不知道服务器的IP,虽然域名服务器也是要把域名解析成IP地址,但不属于应用所关心的范畴,是网络层应该完成的工作。所以Http连接属于无状态的短连接,若再请求其他数据,需要再重新建立连接。客户端向服务器发送请求后,服务器才知道客户端的存在。

TCP连接实现时需要指明IP地址和端口号,就可以跟目的主机通过三次握手建立联系,该连接一直保持直到某一方提出取消连接,通过四次握手关闭连接。Socket支持TCP/UDP协议,如果使用TCP协议,那么socket连接就是TCP连接。论文提到的应用场景是手机与云端的服务器建立联系,因为要保持连接并指定连接的建立时间,所以在这种场景下使用TCP连接最合适。3G网络不支持端到端建立TCP连接,因为它是client-server模式,所以需要通过云端服务器的辅助来实现手机的端到端通信。

你可能感兴趣的:(android,面试,java)