http(比如okhttp框架)
httpUrlConnection安卓的基础网络(volley框架)
httpClient也是安卓的基础网络但是已经不推荐使用新的api不支持了(android-async-http框架)
socket一般使用框架AndroidAsync
webservice一般使用ksoap2-android框架 soap是一种协议
webview能加载显示网页,可以将其视为一个浏览器。它使用了WebKit渲染引擎加载显示网页
okhttp和retrofit职责不同:
另外
在Android中几种网络编程的方式:
(1)针对TCP/IP的Socket、ServerSocket,使用第三方框架AndroidAsync处理
(2)针对直接URL的HttpURLConnection
(3)针对android客户端的httpClient,不过在api21 以上不能使用
(4)Http可以使用okhttp框架
(5)使用Web Service。可以用Ksoap2去实现Webservice
(6) 直接使用WebView视图组件显示网页。
(7)html使用jsoup
网络优化主要从三个方面进行:1. 速度;2. 成功率;3. 流量。
4.1 Gzip压缩
HTTP协议上的Gzip编码是一种用来改进WEB应用程序性能的技术,用来减少传输数据量大小,减少传输数据量大小有两个明显的好处:
4.2 IP直连与HttpDns;
DNS解析的失败率占联网失败中很大一种,而且首次域名解析一般需要几百毫秒。针对此,我们可以不用域名,才用IP直连省去 DNS 解析过程,节省这部分时间。
另外熟悉阿里云的小伙伴肯定知道HttpDns:HttpDNS基于Http协议的域名解析,替代了基于DNS协议向运营商Local DNS发起解析请求的传统方式,可以避免Local DNS造成的域名劫持和跨网访问问题,解决域名解析异常带来的困扰。
4.3 图片处理
4.3.1 图片下载
4.3.2 图片上传
图片(文件)的上传失败率比较高,不仅仅因为大文件,同时带宽、时延、稳定性等因素在此场景下的影响也更加明显;
备注:图片上传是一项看似简单、共性很多但实际上复杂、需要细分的工作。移动互联网的场景和有线的场景是有很多区别的,例如移动网络的质量/带宽经常会发生“跳变”,但有线网络却是“渐变”。
图片上传其它细节请参见《移动App性能评测与优化》一书。
4.4 协议层的优化
使用最新的协议,Http协议有多个版本:0.9、1.0、1.1、2等。新版本的协议经过再次的优化,例如:
新的版本不仅可以节省资源,同样可以减少流量;我对Http2并没有实际接入经验,此处仅从原理进行分析。
4.5 请求打包
合并网络请求,减少请求次数。对于一些接口类如统计,无需实时上报,将统计信息保存在本地,然后根据策略统一上传。这样头信息仅需上传一次,减少了流量也节省了资源。
4.6 网络缓存
对服务端返回数据进行缓存,设定有效时间,有效时间之内不走网络请求,减少流量消耗。对网络的缓存可以参见HttpResponseCache。
备注:我们也可以自定义缓存的实现,一些网络库例如:Volley、Okhttp等都有好的实践供参考。
4.7 网络状态
根据网络状态对网络请求进行区别对待,2G与Wifi状态下网络质量肯定是不一样的,那对应的网络策略也应该是不一样的。例如:在Wifi场景下可以进行数据的预取、一些统计的集中上传等;而在2G场景下此类操作以及网络请求的次数策略都应该调低。网络状态可以由TelephonyManager.getNetworkType()方法获取到。
备注:还可以使用Facebook的开源库network-connection-class来做网络状态的判断。
4.8 其它
断点续传,文件、图片等的下载,采用断点续传,不浪费用户之前消耗过的流量;
重试策略,一次网络请求的失败,需要多次的重试来断定最终的失败,可以参考Volley的重试机制实现。
Protocol Buffer
Protocol Buffer是Google的一种数据交换的格式,它独立于语言,独立于平台。相较于目前常用的Json,数据量更小,意味着传输速度也更快。
具体的对比可以参见:《Protobuffer和json深度对比》。
尽量避免客户端的轮询,而使用服务器推送的方式;
数据更新采用增量,而不是全量,仅将变化的数据返回,客户端进行合并,减少流量消耗;
private class DownThread extends Thread {
@Override
public void run() {
super.run();
String urlStr = "http://xcmserver.b0.upaiyun.com/v1.0/app/" + apatchName;
try {
File file = new File(newFilename);
if (file.exists()) {
urlStr = "http://xcmserver.b0.upaiyun.com/v1.0/app/" + apatchName.replace(".apatch", "new.apatch");
}
Log.i("DownLoadPatchThread", "正在下载中" + urlStr);
// 构造URL
URL url = new URL(urlStr);
// 打开连接
URLConnection con = url.openConnection();
if (con != null) {
// 输入流
InputStream is = con.getInputStream();
File filePath = new File(commonPath);
if (!filePath.exists()) {
boolean bool = filePath.mkdirs();
if (bool) Log.e("DownLoadPatchThread", "创建文件夹");
}
//如果目标文件已经存在,则删除。产生覆盖旧文件的效果
if (file.exists()) {
boolean bool = file.delete();
if (bool) Log.e("DownLoadPatchThread", "删除文件");
}
// 1K的数据缓冲
byte[] bs = new byte[1024];
// 读取到的数据长度
int len;
// 输出的文件流
if (!StringUtils.isEmpty(newFilename)) {
OutputStream os = new FileOutputStream(newFilename);
// 开始读取
while ((len = is.read(bs)) != -1) {
os.write(bs, 0, len);
}
// 完毕,关闭所有链接
os.close();
}
is.close();
Log.i("DownLoadPatchThread", "下载完毕");
File file_out = new File(newFilename);
//如果目标文件已经存在,则删除。产生覆盖旧文件的效果
if (file_out.exists()) {
if (MyApplication.getInstance().getmPatchManager() != null) {
MyApplication.getInstance().getmPatchManager().removeAllPatch();
MyApplication.getInstance().getmPatchManager().addPatch(newFilename);
Log.i("DownLoadPatchThread", newFilename + "加载补丁完毕");
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}