我们知道大多数的 Android 应用程序都是通过和服务器进行交互来获取数据的。如果使用 HTTP 协议来发送和接收网络数据,就免不了使用 HttpURLConnection 和 HttpClient,而 Android 中主要提供了上述两种方式来进行 HTTP 操作。并且这两种方式都支持 HTTPS 协议、以流的形式进行上传和下载、配置超时时间、IPv6、以及连接池等功能。

但是 Googl e发布 6.0 版本的时候声明原生剔除 HttpClient,但是笔者认为 HttpClient 会提供相应的 jar 包做支持,毕竟 Google 对向下兼容这方面一直都做的很好,相信在选择网络功能的时候我们会选自己喜欢的方法。

HttpURLConnection

接着我们来看一下如何使用 HttpURLConnection 来处理简单的网络请求。

// Get方式请求
public static void requestByGet() throws Exception {  String path = "10.128.7.34:3000/name=helloworld&password=android";  // 新建一个URL对象  URL url = new URL(path);  // 打开一个HttpURLConnection连接  HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();  // 设置连接超时时间  urlConn.setConnectTimeout(6 * 1000);  // 开始连接  urlConn.connect();  // 判断请求是否成功  if (urlConn.getResponseCode() == HTTP_200) {  // 获取返回的数据  byte[] data = readStream(urlConn.getInputStream());  Log.i(TAG_GET, new String(data, "UTF-8"));  } else {  Log.i(TAG_GET, "Get方式请求失败");  }  // 关闭连接  urlConn.disconnect();
}  
// Post方式请求
public static void requestByPost() throws Throwable {  String path = "http://10.128.7.34:3000/login";  // 请求的参数转换为byte数组  String params = "name" + URLEncoder.encode("helloworld", "UTF-8")  + "&password=" + URLEncoder.encode("android", "UTF-8");  byte[] postData = params.getBytes();  // 新建一个URL对象  URL url = new URL(path);  // 打开一个HttpURLConnection连接  HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();  // 设置连接超时时间  urlConn.setConnectTimeout(5 * 1000);  // Post请求必须设置允许输出  urlConn.setDoOutput(true);  // Post请求不能使用缓存  urlConn.setUseCaches(false);  // 设置为Post请求  urlConn.setRequestMethod("POST");  urlConn.setInstanceFollowRedirects(true);  // 配置请求Content-Type  urlConn.setRequestProperty("Content-Type","application/x-www-form-urlencode");  // 开始连接  urlConn.connect();  // 发送请求参数  DataOutputStream dos = new DataOutputStream(urlConn.getOutputStream());  dos.write(postData);  dos.flush();  dos.close();  // 判断请求是否成功  if (urlConn.getResponseCode() == HTTP_200) {  // 获取返回的数据  byte[] data = readStream(urlConn.getInputStream());  Log.i(TAG_POST, new String(data, "UTF-8"));  } else {  Log.i(TAG_POST, "Post方式请求失败");  }
}  

关于HttpURLConnection的相关开源工程

由于 Google 已经表明了推荐广大开发者使用 HttpURLConnection,那么想必是有一定原因的。

xUtils3

这里就推荐大伙都很熟悉的开源项目 xUtils 的“弟弟“,xUtils3。xUtils 包含了 view 注入,图片处理,数据库操作以及网络请求封装,xUtils 使用的网络请求封装是基于 HttpClient 的。xUtils3 使用的网络请求是基于 HttpURLConnection,我们着重说明一下xUtils3。

RequestParams params = new RequestParams("http://10.128.7.34:3000/upload");  // 加到url里的参数, http://xxxx/s?wd=xUtilsparams.addQueryStringParameter("wd", "xUtils");// 添加到请求 body 体的参数, 只有 POST, PUT, PATCH, DELETE 请求支持.// params.addBodyParameter("wd", "xUtils");// 使用 multipart 表单上传文件params.setMultipart(true);params.addBodyParameter("file",new File("/sdcard/test.jpg"),null); // 如果文件没有扩展名, 最好设置contentType 参数.params.addBodyParameter("file2",new FileInputStream(new File("/sdcard/test2.jpg")),"image/jpeg",// 测试中文文件名"你+& \" 好.jpg"); // InputStream 参数获取不到文件名, 最好设置, 除非服务端不关心这个参数.x.http().post(params, new Callback.CommonCallback<String>() {@Overridepublic void onSuccess(String result) {Toast.makeText(x.app(), result, Toast.LENGTH_LONG).show();}@Overridepublic void onError(Throwable ex, boolean isOnCallback) {Toast.makeText(x.app(), ex.getMessage(), Toast.LENGTH_LONG).show();}@Overridepublic void onCancelled(CancelledException cex) {Toast.makeText(x.app(), "cancelled", Toast.LENGTH_LONG).show();}@Overridepublic void onFinished() {}});

具有 cache 功能

RequestParams params = new RequestParams("http://10.128.7.34:3000/upload");  params.wd = "xUtils";// 默认缓存存活时间, 单位:毫秒.(如果服务没有返回有效的max-age 或 Expires)params.setCacheMaxAge(1000 * 60);Callback.Cancelable cancelable// 使用 CacheCallback, xUtils 将为该请求缓存数据.= x.http().get(params, new Callback.CacheCallback<String>() {private boolean hasError = false;private String result = null;@Overridepublic boolean onCache(String result) {// 得到缓存数据, 缓存过期后不会进入这个方法.// 如果服务端没有返回过期时间, 参考params.setCacheMaxAge(maxAge)方法.//// * 客户端会根据服务端返回的 header 中 max-age 或 expires 来确定本地缓存是否给 onCache 方法.//   如果服务端没有返回 max-age 或 expires, 那么缓存将一直保存, 除非这里自己定义了返回false的//   逻辑, 那么xUtils将请求新数据, 来覆盖它.//// * 如果信任该缓存返回 true, 将不再请求网络;//   返回 false 继续请求网络, 但会在请求头中加上ETag, Last-Modified等信息,//   如果服务端返回 304, 则表示数据没有更新, 不继续加载数据.//this.result = result;return false; // true: 信任缓存数据, 不在发起网络请求; false 不信任缓存数据.}@Overridepublic void onSuccess(String result) {// 注意: 如果服务返回 304 或 onCache 选择了信任缓存, 这里将不会被调用,// 但是 onFinished 总会被调用.this.result = result;}@Overridepublic void onError(Throwable ex, boolean isOnCallback) {hasError = true;Toast.makeText(x.app(), ex.getMessage(), Toast.LENGTH_LONG).show();if (ex instanceof HttpException) { // 网络错误HttpException httpEx = (HttpException) ex;int responseCode = httpEx.getCode();String responseMsg = httpEx.getMessage();String errorResult = httpEx.getResult();// ...} else { // 其他错误// ...}}@Overridepublic void onCancelled(CancelledException cex) {Toast.makeText(x.app(), "cancelled", Toast.LENGTH_LONG).show();}@Overridepublic void onFinished() {if (!hasError && result != null) {// 成功获取数据Toast.makeText(x.app(), result, Toast.LENGTH_LONG).show();}}});

post请求直接更改 post 方式,以及需要提交的参数即可,篇幅问题这里就不在一一列举了。通过以上代码可以看到,我们在使用 xUtils 来请求网络的时候会非常的方便,只用在回调函数里面做对应的代码逻辑处理即可,不用关心线程问题,极大的解放了我们的生产力。
Android Stuido Gradle使用方法如下:

compile 'org.xutils:xutils:3.1.+'

Volley

在 Android 2.3 及以上版本,使用的是 HttpURLConnection,而在Android 2.2 及以下版本,使用的是 HttpClient。鉴于现在的手机行业发展速度,我们已经不考虑 Android2.2 了。

简单提供一些 Volley 的实例:

//简单的 GET 请求
mQueue = Volley.newRequestQueue(getApplicationContext());
mQueue.add(new JsonObjectRequest(Method.GET, url, null,  new Listener() {  @Override  public void onResponse(JSONObject response) {  Log.d(TAG, "response : " + response.toString());  }  }, null));
mQueue.start();
//对 ImageView 的操作
ImageListener listener = ImageLoader.getImageListener(imageView, android.R.drawable.ic_launcher, android.R.drawable.ic_launcher);
mImageLoader.get(url, listener);  //对 ImageView 网络加载的处理
mImageView.setImageUrl(url, imageLoader);
当然我们也可以定制自己的 requestmRequestQueue.add( new GsonRequest(url, ListResponse.class, null,  new Listener() {  public void onResponse(ListResponse response) {  appendItemsToList(response.item);  notifyDataSetChanged();  }  }
}

HttpClient

同样,我们来看一下 HttpClient 的简单请求。

// HttpGet 方式请求
public static void requestByHttpGet() throws Exception {  String path = "http://10.128.7.34:3000/name=helloworld&password=android";  // 新建 HttpGet 对象  HttpGet httpGet = new HttpGet(path);  // 获取 HttpClient 对象  HttpClient httpClient = new DefaultHttpClient();  // 获取 HttpResponse 实例  HttpResponse httpResp = httpClient.execute(httpGet);  // 判断是够请求成功  if (httpResp.getStatusLine().getStatusCode() == HTTP_200) {  // 获取返回的数据  String result = EntityUtils.toString(httpResp.getEntity(), "UTF-8");  Log.i(TAG_HTTPGET, "HttpGet 方式请求成功,返回数据如下:");  Log.i(TAG_HTTPGET, result);  } else {  Log.i(TAG_HTTPGET, "HttpGet 方式请求失败");  }
}
// HttpPost 方式请求
public static void requestByHttpPost() throws Exception {  String path = "https://reg.163.com/login";  // 新建 HttpPost 对象  HttpPost httpPost = new HttpPost(path);  // Post 参数  List<NameValuePair> params = new ArrayList<NameValuePair>();  params.add(new BasicNameValuePair("name", "helloworld"));  params.add(new BasicNameValuePair("password", "android"));  // 设置字符集  HttpEntity entity = new UrlEncodedFormEntity(params, HTTP.UTF_8);  // 设置参数实体  httpPost.setEntity(entity);  // 获取 HttpClient 对象  HttpClient httpClient = new DefaultHttpClient();  // 获取 HttpResponse 实例  HttpResponse httpResp = httpClient.execute(httpPost);  // 判断是够请求成功  if (httpResp.getStatusLine().getStatusCode() == HTTP_200) {  // 获取返回的数据  String result = EntityUtils.toString(httpResp.getEntity(), "UTF-8");  Log.i(TAG_HTTPGET, "HttpPost 方式请求成功,返回数据如下:");  Log.i(TAG_HTTPGET, result);  } else {  Log.i(TAG_HTTPGET, "HttpPost 方式请求失败");  }
}  

关于 HttpClinet 的相关开源工程

HttpClient 也拥有这大量优秀的开源工程,afinal、xUtils 以及AsyncHttpClient,也可以为广大开发者提供已经造好的轮子。由于xUtils 是基于 afinal 重写的,现在 xUtils3 也有替代 xUtils 的趋势,所以我们在这就简单介绍一下 AsyncHttpClient。

AsyncHttpClient

见名知意,AsyncHttpClient 对处理异步 Http 请求相当擅长,并通过匿名内部类处理回调结果,Http 异步请求均位于非 UI 线程,不会阻塞 UI 操作,通过线程池处理并发请求处理文件上传、下载、响应结果自动打包 JSON 格式。使用起来会很方便。

//GET请求
AsyncHttpClient client = new AsyncHttpClient();
//当然这里也可以换成 new JsonHttpResponseHandler(),我们就能直接获得 JSON 数据了。
client.get("http://www.google.com", new AsyncHttpResponseHandler() {@Overridepublic void onStart() {// called before request is started}@Overridepublic void onSuccess(int statusCode, Header[] headers, byte[] response) {// called when response HTTP status is "200 OK"}@Overridepublic void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {// called when response HTTP status is "4XX" (eg. 401, 403, 404)}@Overridepublic void onRetry(int retryNo) {// called when request is retried}
});
//POST 请求
AsyncHttpClient client = new AsyncHttpClient();
RequestParams params = new RequestParams();
params.put("key", "value");
params.put("more", "data");
//同上,这里一样可以改成处理 JSON 数据的方法
client.get("http://www.google.com", params, new  TextHttpResponseHandler() {@Overridepublic void onSuccess(int statusCode, Header[] headers, String response) {System.out.println(response);}@Overridepublic void onFailure(int statusCode, Header[] headers, String responseBody, Throwable error) {Log.d("ERROR", error);}    }
);

经过上面的代码发现,AsyncHttpClient 使用起来也是异常简洁,主要靠回调方法来处理成功或失败之后的逻辑。仔细想想,xUtils 的处理方式和这个处理方式很类似,看来好用设计还是很受人青睐的。

OkHttp

如果两种网络请求都想使用怎么办?那么 OkHttp 是一个最佳解决方案了。

OkHttp 在网络请求方面的口碑很好,就连 Google 自己也有使用OkHttp。虽然 Google6.0 中剔除了 HttpClient 的 Api,但是由于OkHttp 的影响力以及其强大的功能,使用 OkHttp 无需重写您程序中的网络代码。同时最重要的一点 OkHttp 实现了几乎和java.net.HttpURLConnection 一样的 API。如果您用了 Apache HttpClient,则 OkHttp 也提供了一个对应的 okhttp-apache 模块。足以说明 OkHttp 的强大,下面是一些例子。

  • 一般的 get 请求
  • 一般的 post 请求
  • 基于 Http 的文件上传
  • 文件下载
  • 加载图片
  • 支持请求回调,直接返回对象、对象集合
  • 支持 session 的保持

简单代码实例

//GET 请求
OkHttpClient client = new OkHttpClient();String run(String url) throws IOException {  Request request = new Request.Builder().url(url).build();Response response = client.newCall(request).execute();return response.body().string();
}
//POST 请求
public static final MediaType JSON  = MediaType.parse("application/json; charset=utf-8");OkHttpClient client = new OkHttpClient();String post(String url, String json) throws IOException {  RequestBody body = RequestBody.create(JSON, json);Request request = new Request.Builder().url(url).post(body).build();Response response = client.newCall(request).execute();return response.body().string();
}

Android Studio Gradle 使用方式:

compile 'com.squareup.okhttp:okhttp:3.7.0'

总结

Android 开发应用少不了使用网络,移动互联时代,抢占终端入口变得异常重要,那么我们在开发过程中,不管使用哪一种网络请求,HttpURLConnection 或者是 HttpClient,都可以满足我们和服务器的沟通。

Android 网络请求详解相关推荐

  1. Android 网络属性详解

    在实际开发中,我们可能会遇到需要判断当前Android设备的网络等方面的需求,这里所说的网络是指WiFi和手机移动网络,也就是指手机的上网方式.最近有空,就来总结有关Android网络方面的.废话不多 ...

  2. afn访问本地html,Swift利用AFN实现封装网络请求详解

    前言 相信大家都知道,我们一般在一个项目中,网络请求都封装成一个单例,以确保整个项目的网络请求 Session 是同一个. 单例模式定义:一个类有且仅有一个实例,并且自行实例化向整个系统提供,下面话不 ...

  3. AFNetworking网络请求详解

    一.AFURLSessionManager 网络请求的核心类,主要作用有以下几点: 1.线程安全的创建NSURLSession,并实现NSURLSessionDelegate 2.设置response ...

  4. android 的监控讲解,java android网络监测详解

    public class NetworkCheck { /** * 网络是否可用 */ public static boolean isNetworkAvailable(Context context ...

  5. okhttp的应用详解与源码解析--android网络请求框架发展史

    乘5G之势,借物联网之风,Android未来亦可期,Android优势在于开放,手机.平板.车载设备.智能家居等都是Android的舞台,Google不倒,Android不灭,本专栏的同步视频教程已经 ...

  6. Android Studio 插件开发详解二:工具类

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/78112856 本文出自[赵彦军的博客] 在插件开发过程中,我们按照开发一个正式的项 ...

  7. Android LiveData组件详解以及LiveDataBus

    转载请标明出处:https://blog.csdn.net/zhaoyanjun6/article/details/99749323 本文出自[赵彦军的博客] 一.LiveData简介 LiveDat ...

  8. Android OkHttp 全面详解

    Android OkHttp 全面详解 包的导入 基本使用 异步请求 同步请求 build创建 源码跟踪 newCall RealCall.enqueue Dispatcher.enqueue exe ...

  9. Carson带你学Android:图文详解RxJava背压策略

    前言 Rxjava,由于其基于事件流的链式调用.逻辑简洁 & 使用简单的特点,深受各大 Android开发者的欢迎. 本文主要讲解的是RxJava中的 背压控制策略,希望你们会喜欢. Cars ...

最新文章

  1. 《Pokemon Go》开发商明年将推出「哈利波特」题材AR游戏
  2. flyway使用简介
  3. ios上架图片在线制作_TF上架是什么?上架testflight真的不掉签吗?
  4. linux 线程退出 signal,Linux signal 那些事儿 (3)
  5. 商用彩信服务成为企业3G应用新需求
  6. 遍历children_589. N叉树的前序遍历
  7. 模拟知乎登陆(requests和scrapy)
  8. 严格对角占优矩阵特征值_二次型和特征值
  9. 后台访问突然出现一串代码,且不能显示页面
  10. ORC File文件结构
  11. Cadence Allegro剪断走线图文教程及视频演示
  12. Excel多个sheet导出pdf
  13. 【AutoHotkey】笔记本键盘没有Home键和End键的解决方案
  14. Android的启动流程
  15. 漫画 | 30年后,中国就会有自己的编程语言!
  16. 什么是ITCM和DTCM?
  17. 1D卷积入门:一维卷积是如何处理数字信号的
  18. unity anima2d_Unity通过Anima2D扩展2D产品
  19. Adobe 官方公布的 RTMP 规范+未公布的部分
  20. C++中public:的意思

热门文章

  1. 做CEO,一定要有“江湖感”
  2. 俄语版TikTok风靡俄罗斯
  3. 路由异常的起源-如何影响最终用户?——Vecloud微云
  4. TCP首部和TCP的特性—Vecloud微云
  5. Kettle实例解析
  6. linux关于禁用硬件xinput使用
  7. SQL Inject of Code to bypass
  8. 针对maven install 报错:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1 解决方案...
  9. ssh密钥分发之二:使用sshpass配合ssh-kopy-id编写脚本批量分发密钥:
  10. “cannot find module ‘npmlog’….”的错误