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效果,如果可以用<shape/>画的就尽量不要直接引用图片资源了,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<gradient android:startColor="#000000"
android:angle="0" android:endColor="#ffffff"/>
</shape>
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模式,所以需要通过云端服务器的辅助来实现手机的端到端通信。