Android - 网络基础
Android网络请求心路历程
HttpURLConnection和HttpClient对比:
http://blog.csdn.net/guolin_blog/article/details/12452307
HttpURL基本封装
http://www.jianshu.com/p/3141d4e46240
HTTP缓存机制
缓存对于移动端是非常重要的存在。
- 减少请求次数,减小服务器压力.
- 本地数据读取速度更快,让页面不会空白几百毫秒。
- 在无网络的情况下提供数据。
缓存一般由服务器控制(通过某些方式可以本地控制缓存,比如向过滤器添加缓存控制信息)。
Request
请求头字段 | 意义 |
---|---|
If-Modified-Since: Sun, 03 Jan 2016 03:47:16 GMT | 缓存文件的最后修改时间。 |
If-None-Match: "3415g77s19tc3:0" | 缓存文件的Etag(Hash)值 |
Cache-Control: no-cache | 不使用缓存 |
Pragma: no-cache | 不使用缓存 |
Response
响应头字段 | 意义 |
---|---|
Cache-Control: public | 响应被共有缓存,移动端无用 |
Cache-Control: private | 响应被私有缓存,移动端无用 |
Cache-Control:no-cache | 不缓存 |
Cache-Control:no-store | 不缓存 |
Cache-Control: max-age=60 | 60秒之后缓存过期(相对时间) |
Date: Sun, 03 Jan 2016 04:07:01 GMT | 当前response发送的时间 |
Expires: Sun, 03 Jan 2016 07:07:01 GMT | 缓存过期的时间(绝对时间) |
Last-Modified: Sun, 03 Jan 2016 04:07:01 GMT | 服务器端文件的最后修改时间 |
ETag: "3415g77s19tc3:0" | 服务器端文件的Etag[Hash]值 |
正式使用时按需求也许只包含其中部分字段。
客户端要根据这些信息储存这次请求信息。
然后在客户端发起请求的时候要检查缓存。遵循下面步骤:
Volley&OkHttp
Volley&OkHttp应该是现在最常用的网络请求库。用法也非常相似。都是用构造请求加入请求队列的方式管理网络请求。
先说Volley:
Volley可以通过这个库进行依赖.
Volley在Android 2.3及以上版本,使用的是HttpURLConnection,而在Android 2.2及以下版本,使用的是HttpClient。
Volley的基本用法,网上资料无数,这里推荐郭霖大神的博客
Volley存在一个缓存线程,一个网络请求线程池(默认4个线程)。
Volley这样直接用开发效率会比较低,我将我使用Volley时的各种技巧封装成了一个库RequestVolly.
我在这个库中将构造请求的方式封装为了函数式调用。维持一个全局的请求队列,拓展一些方便的API。
不过再怎么封装Volley在功能拓展性上始终无法与OkHttp相比。
Volley停止了更新,而OkHttp得到了官方的认可,并在不断优化。
因此我最终替换为了OkHttp
OkHttp用法见这里
很友好的API与详尽的文档。
这篇文章也写的很详细了。
OkHttp使用Okio进行数据传输。都是Square家的。
但并不是直接用OkHttp。Square公司还出了一个Retrofit库配合OkHttp战斗力翻倍。
Retrofit&RestAPI
Retrofit极大的简化了网络请求的操作,它应该说只是一个Rest API管理库,它是直接使用OKHttp进行网络请求并不影响你对OkHttp进行配置。毕竟都是Square公司出品。
RestAPI是一种软件设计风格。
服务器作为资源存放地。客户端去请求GET,PUT, POST,DELETE资源。并且是无状态的,没有session的参与。
移动端与服务器交互最重要的就是API的设计。比如这是一个标准的登录接口。
你们应该看的出这个接口对应的请求包与响应包大概是什么样子吧。
请求方式,请求参数,响应数据,都很清晰。
使用Retrofit这些API可以直观的体现在代码中。
然后使用Retrofit提供给你的这个接口的实现类 就能直接进行网络请求获得结构数据。
注意Retrofit2.0相较1.9进行了大量不兼容更新。google上大部分教程都是基于1.9的。这里有个2.0的教程。
教程里进行异步请求是使用Call。Retrofit最强大的地方在于支持RxJava。就像我上图中返回的是一个Observable。RxJava上手难度比较高,但用过就再也离不开了。Retrofit+OkHttp+RxJava配合框架打出成吨的输出,这里不再多说。
网络请求学习到这里我觉得已经到顶了。。
网络图片加载优化
对于图片的传输,就像上面的登录接口的avatar字段,并不会直接把图片写在返回内容里,而是给一个图片的地址。需要时再去加载。
如果你直接用HttpURLConnection去取一张图片,你办得到,不过没优化就只是个BUG不断demo。绝对不能正式使用。
注意网络图片有些特点:
- 它永远不会变
一个链接对应的图片一般永远不会变,所以当第一次加载了图片时,就应该予以永久缓存,以后就不再网络请求。 - 它很占内存
一张图片小的几十k多的几M高清无码。尺寸也是64*64到2k图。你不能就这样直接显示到UI,甚至不能直接放进内存。 - 它要加载很久
加载一张图片需要几百ms到几m。这期间的UI占位图功能也是必须考虑的。
说说我在上面提到的RequestVolley里做的图片请求处理(没错我做了,这部分的代码可以去github里看源码)。
三级缓存
网上常说三级缓存--服务器,文件,内存。不过我觉得服务器不算是一级缓存,那就是数据源嘛。
内存缓存
首先内存缓存使用LruCache。LRU是Least Recently Used 近期最少使用算法,这里确定一个大小,当Map里对象大小总和大于这个大小时将使用频率最低的对象释放。我将内存大小限制为进程可用内存的1/8.
内存缓存里读得到的数据就直接返回,读不到的向硬盘缓存要数据。硬盘缓存
硬盘缓存使用DiskLruCache。这个类不在API中。得复制使用。
看见LRU就明白了吧。我将硬盘缓存大小设置为100M。
@Override
public void putBitmap(String url, Bitmap bitmap) {
put(url, bitmap);
//向内存Lru缓存存放数据时,主动放进硬盘缓存里
try {
Editor editor = mDiskLruCache.edit(hashKeyForDisk(url));
bitmap.compress(Bitmap.CompressFormat.JPEG, , editor.newOutputStream());
editor.commit();
} catch (IOException e) {
e.printStackTrace();
}
} //当内存Lru缓存中没有所需数据时,调用创造。
@Override
protected Bitmap create(String url) {
//获取key
String key = hashKeyForDisk(url);
//从硬盘读取数据
Bitmap bitmap = null;
try {
DiskLruCache.Snapshot snapShot = mDiskLruCache.get(key);
if(snapShot!=null){
bitmap = BitmapFactory.decodeStream(snapShot.getInputStream());
}
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
DiskLruCache的原理不再解释了(我还解决了它存在的一个BUG,向Log中添加的数据增删记录时,最后一条没有输出,导致最后一条缓存一直失效。)
- 硬盘缓存也没有数据就返回空,然后就向服务器请求数据。
这就是整个流程。
但我这样的处理方案还是有很多局限。
- 图片未经压缩处理直接存储使用
- 文件操作在主线程
- 没有完善的图片处理API
以前也觉得这样已经足够好直到我遇到下面俩。
Fresco&Glide
不用想也知道它们都做了非常完善的优化,重复造轮子的行为很蠢。
Fresco是Facebook公司的黑科技。光看功能介绍就看出非常强大。使用方法官方博客说的够详细了。
真三级缓存,变换后的BItmap(内存),变换前的原始图片(内存),硬盘缓存。
在内存管理上做到了极致。对于重度图片使用的APP应该是非常好的。
它一般是直接使用SimpleDraweeView
来替换ImageView
,呃~侵入性较强,依赖上它apk包直接大1M。代码量惊人。
所以我更喜欢Glide,作者是bumptech。这个库被广泛的运用在google的开源项目中,包括2014年google I/O大会上发布的官方app。
这里有详细介绍。直接使用ImageView即可,无需初始化,极简的API,丰富的拓展,链式调用都是我喜欢的。
丰富的拓展指的就是这个。
另外我也用过Picasso。API与Glide简直一模一样,功能略少,且有半年未修复的BUG。
图片管理方案
再说说图片存储。不要存在自己服务器上面,徒增流量压力,还没有图片处理功能。
推荐七牛与阿里云存储(没用过其它 π__π )。它们都有很重要的一项图片处理。在图片Url上加上参数来对图片进行一些处理再传输。
于是(七牛的处理代码)
public static String getSmallImage(String image){
if (image==null)return null;
if (isQiniuAddress(image)) image+="?imageView2/0/w/"+IMAGE_SIZE_SMALL;
return image;
} public static String getLargeImage(String image){
if (image==null)return null;
if (isQiniuAddress(image)) image+="?imageView2/0/w/"+IMAGE_SIZE_LARGE;
return image;
} public static String getSizeImage(String image,int width){
if (image==null)return null;
if (isQiniuAddress(image)) image+="?imageView2/0/w/"+width;
return image;
}
既可以加快请求速度,又能减少流量。再配合Fresco或Glide。完美的图片加载方案。
不过这就需要你把所有图片都存放在七牛或阿里云,这样也不错。
图片/文件上传也都是使用它们第三方存储,它们都有SDK与官方文档教你。
不过图片一定要压缩过后上传。上传1-2M大的高清照片没意义。
Android - 网络基础的更多相关文章
- 迈向高阶:优秀Android程序员必知必会的网络基础
1.前言 网络通信一直是Android项目里比较重要的一个模块,Android开源项目上出现过很多优秀的网络框架,从一开始只是一些对HttpClient和HttpUrlConnection简易封装使用 ...
- Android网络编程基础
Android网络编程只TCP通信 TCP 服务器端工作的主要步骤如下.步骤1 调用ServerSocket(int port)创建一个ServerSocket,并绑定到指定端口上.步骤2 调用acc ...
- Android网络之数据解析----SAX方式解析XML数据
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
- Android网络编程系列 一 TCP/IP协议族
在学习和使用Android网路编程时,我们接触的仅仅是上层协议和接口如Apache的httpclient或者Android自带的httpURlconnection等等.对于这些接口的底层实现我们也有必 ...
- Android网络编程系列 一 Socket抽象层
在<Android网络编程>系列文章中,前面已经将Java的通信底层大致的描述了,在我们了解了TCP/IP通信族架构及其原理,接下来我们就开始来了解基于tcp/ip协议层的Socket抽 ...
- AndroidApplication Fundamentals(Android应用基础)
AndroidApplication Fundamentals(Android应用基础) Android应用采用Java编程语言来编写,AndroidSDK工具编译我们的代码,连同任何数据和资源文件一 ...
- 【Android 应用开发】Android 网络编程 API笔记 - java.net 包 权限 地址 套接字 相关类 简介
Android 网络编程相关的包 : 9 包, 20 接口, 103 类, 6 枚举, 14异常; -- Java包 : java.net 包 (6接口, 34类, 2枚举, 12异常); -- An ...
- 【Android 应用开发】Android 网络编程 API笔记 - java.net 包相关 接口 api
Android 网络编程相关的包 : 9 包, 20 接口, 103 类, 6 枚举, 14异常; -- Java包 : java.net 包 (6接口, 34类, 2枚举, 12异常); -- An ...
- Android BLE与终端通信(二)——Android Bluetooth基础科普以及搜索蓝牙设备显示列表
Android BLE与终端通信(二)--Android Bluetooth基础搜索蓝牙设备显示列表 摘要 第一篇算是个热身,这一片开始来写些硬菜了,这篇就是实际和蓝牙打交道了,所以要用到真机调试哟, ...
随机推荐
- Linux下安装MySQL以及一些小坑
第一次写博客,各位凑合着看吧(假装有人看). 我这里使用的是centos7. 1.首先打开终端,查看有没有安装过MySQL: [root@localhost lyp]# rpm -qa | grep ...
- Ms17-010进行WEB提权之实践下某培训靶机服务器
前言:该机器为某个其他培训机构的靶机,说实话在这里没炫耀啥,只是给各位学习Ms17010的同学指一条路,我原先也折腾这玩意儿好久,但是就是不行,最近才找到了出路,所以多写两篇文章,把各种需要注意的地方 ...
- 【ElasticSearch】:Windows下ElasticSearch+版本安装head
概述 elasticsearch-head,之前插件plugin方式已废弃,现已改为nodejs的NPM安装,独立WEB服务方式. elasticsearch-head网址:https://githu ...
- 在vue项目中stylus的安装及使用
Stylus是一个CSS预处理器. Stylus安装包安装: dell@DESKTOP-KD0EJ4H MINGW64 /f/gsff-frone $ cnpm install stylus --sa ...
- [Umbraco] 创建第一个页面
如何创建一个页面,很简单. 进入settings,首先右键点击“Document Types”, 在出现的菜单点击"Create",在弹出的窗口中 Master Document ...
- odoo配置界面设置字段默认值
转自国外牛人博客:http://ludwiktrammer.github.io/odoo/custom-settings-odoo.html Defining custom settings in O ...
- 前端安全 -- XSS攻击
XSS漏洞是最广泛.作用最关键的web安全漏洞之一.在绝大多数网络攻击中都是把XSS作为漏洞链中的第一环,通过XSS,黑客可以得到的最直接利益就是拿到用户浏览器的cookie,从而变相盗取用户的账号密 ...
- 怎么样imageview实现铺满全屏
<ImageView android:layout_width="match_parent" android:layout_height="match_parent ...
- sql字符处理
--Description: 字符处理 --使用: 放到查询分析器里执行就可以了 --示例: select * from dbo.splitstr('12 44 45 50 56 87',' ') o ...
- Node.js 安装及环境配置之 Windows 篇
一.安装环境 1.本机系统:Windows 10 企业版(64位)2.Node.js:node-v8.9.4-x64.msi(64位) 二.安装Node.js步骤 1.下载对应自己系统对应的 Node ...