首页 > 代码库 > Android开发之网络请求通信专题(一):基于HttpURLConnection的请求通信
Android开发之网络请求通信专题(一):基于HttpURLConnection的请求通信
在Android开发中,网络请求必然是必不可少。一般而言,都是基于http的网络请求。有时候也会有SOCKET请求,这个后续的专题再讲。今天,我们就先讲讲常用的Http请求。
http求情自然是遵循http协议的,相关内容请转接:Java学习笔记之Http协议详解
好了,开始今天的正题。
一、基础HTTPURL请求方式
我们先来看一个最简单的例子,通过get方法请求拿到返回值
1、用get方式请求
URL url = new URL( "http://192.168.31.144:10010/MINATest/servlet/DataTestServlet?username=victor&password=strikefreedom"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(TIME); conn.setReadTimeout(TIME); int responseCode = conn.getResponseCode(); if (responseCode == 200) { input = conn.getInputStream(); if (input != null) { //拿到流后处理 } }
2、用post方式请求
String data = http://www.mamicode.com/"username=justice&password=infiniteJustice";>
我们可以看到用post方式请求和用get方式传入参数有点不同。
二、http访问类的封装
1、封装逻辑
我们知道,在android开发中,网络访问的东西都是不能再UI线程中执行的,只能在子线程里面执行,得到结果后通知主线程刷新UI。这个消息通知机制博主就不在详细秒速,有兴趣的朋友请转接:Android异步处理系列文章索引
在正常的开发中,我们不会每次请求,都像上面那样的简单去写,我们需要做一定的封装处理,来使代码更加的简洁,架构更加的清晰。那么我们需要这么四个东西
1、http访问管理者
2、消息通信管理者handler
3、http访问结果监听器
4、http访问结果事件处理回调接口。
整个逻辑关系为:http访问管理者采用get或者post请求方式请求,当产生结果后监听器告诉消息通信管理者应该发送什么消息给UI线程,UI线程更具消息通信管理者发送过来的消息,调用对应的事件处理回调接口。
那么我们来一一对应看这四个类该如何编写。
2、http访问管理者
http访问管理者,如其名,里面需要封装两种请求。正常情况下,在构造出http访问管理者的时候,需要传入一个通信协议的类进入,里面应该包含请求地址以及请求信息,这里博主为了方便省事,没有出入,直接写死了。有兴趣的同学可以根据自身实际需求更改。看代码:
package com.example.nettest; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.SocketException; import java.net.SocketTimeoutException; import java.net.URL; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; import android.content.Context; import android.text.TextUtils; import android.util.Log; /** * @ClassName: FreedomHttpUrlUtils * @author victor_freedom (x_freedom_reddevil@126.com) * @createddate 2015-1-22 下午1:43:58 * @Description: http请求管理者 */ public class FreedomHttpUrlUtils implements Runnable { private Context context; /** http访问结果监听器 */ private FreedomHttpListener listener; /** 当前访问线程 */ private Thread currentRequest = null; /** 访问链接 */ HttpURLConnection conn = null; /** 拿到的流 */ InputStream input = null; private static final String ENCODING = "UTF-8"; public static final int GET_MOTHOD = 1; private static final int TIME = 40 * 1000; public static final int POST_MOTHOD = 2; /** * 1: get请求 2: post请求 */ private int requestStatus = 1; /** * <p> * Title: * </p> * <p> * Description:构造方法,其实在这里可以传入一个传输协议包,博主是测试代码,所以请求中直接写死了。 * </p> * * @param mContext * @param listener * 监听器 * @param mRequeststatus * 请求方式 */ public FreedomHttpUrlUtils(Context mContext, FreedomHttpListener listener, int mRequeststatus) { this.context = mContext; this.requestStatus = mRequeststatus; this.listener = listener; } /** * @Title: postRequest * @Description:Post请求触发 * @throws */ public void postRequest() { requestStatus = 2; currentRequest = new Thread(this); currentRequest.start(); } /** * @Title: getRequeest * @Description:GET请求触发 * @throws */ public void getRequeest() { requestStatus = 1; currentRequest = new Thread(this); currentRequest.start(); } /** * 对请求的字符串进行编码 * * @return * @throws UnsupportedEncodingException */ public static String requestEncodeStr(String requestStr) throws UnsupportedEncodingException { return URLEncoder.encode(requestStr, ENCODING); } /** * @Title: sendGetRequest * @Description: 发送get请求 * @throws */ private void sendGetRequest() { try { URL url = new URL( "http://192.168.31.144:10010/MINATest/servlet/DataTestServlet?username=victor&password=strikefreedom"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(TIME); conn.setReadTimeout(TIME); int responseCode = conn.getResponseCode(); if (responseCode == 200) { input = conn.getInputStream(); if (input != null) { listener.action(FreedomHttpListener.EVENT_GET_DATA_SUCCESS, readStream(input)); } } else { listener.action(FreedomHttpListener.EVENT_NETWORD_EEEOR, null); } } catch (SocketException e) { e.printStackTrace(); listener.action(FreedomHttpListener.EVENT_CLOSE_SOCKET, null); } catch (SocketTimeoutException e) { e.printStackTrace(); listener.action(FreedomHttpListener.EVENT_NETWORD_EEEOR, null); } catch (IOException e) { e.printStackTrace(); listener.action(FreedomHttpListener.EVENT_GET_DATA_EEEOR, null); } catch (Exception e) { e.printStackTrace(); listener.action(FreedomHttpListener.EVENT_NETWORD_EEEOR, null); } } /** * @Title: sendPostRequest * @Description: 发送post请求 * @throws */ private void sendPostRequest() { try { String data = http://www.mamicode.com/"username=justice&password=infiniteJustice";>
我们可以看到,当访问有结果以后,会出发监听器的action方法,那么我们再来看看监听器的定义
3、http访问结果监听器
package com.example.nettest; /** * @ClassName: FreedomHttpListener * @author victor_freedom (x_freedom_reddevil@126.com) * @createddate 2015-1-24 下午4:28:31 * @Description: 监听器 */ public interface FreedomHttpListener { public static final int EVENT_BASE = 0x100; /** * 没有网络的信息提示 * */ public static final int EVENT_NOT_NETWORD = EVENT_BASE + 1; /** * 网络异常的信息提示 * */ public static final int EVENT_NETWORD_EEEOR = EVENT_BASE + 2; /** * 获取网络数据失败 * */ public static final int EVENT_GET_DATA_EEEOR = EVENT_BASE + 3; /** * 获取网络数据成功 * */ public static final int EVENT_GET_DATA_SUCCESS = EVENT_BASE + 4; /** * 获取网络数据成功 * */ public static final int EVENT_CLOSE_SOCKET = EVENT_BASE + 5; public void action(int actionCode, Object object); }
我们可以看到,在触发action动作的时候,我们会传入一个code和一个对象,这个code表示当前访问是否成功,而对象就是要传输的访问结果。
我们再看看消息处理器是如何工作的
4、消息处理器
/** * @ClassName: BaseHandler * @author victor_freedom (x_freedom_reddevil@126.com) * @createddate 2015-1-24 下午4:32:05 * @Description: 消息处理器 */ class BaseHandler extends Handler { private Context context; /** 事件回调接口处理 */ private FreedomDataCallBack callBack; public BaseHandler(Context context, FreedomDataCallBack callBack) { this.context = context; this.callBack = callBack; } public void handleMessage(Message msg) { // 根据不同的结果触发不同的动作 if (msg.what == FreedomHttpListener.EVENT_GET_DATA_SUCCESS) { if (msg.obj == null) { callBack.onFailed(); } else { // 后台处理数据 callBack.processData(msg.obj, true); } } else if (msg.what == FreedomHttpListener.EVENT_NOT_NETWORD) { callBack.onFailed(); // CommonUtil.showInfoDialog(context, // getString(R.string.net_error)); } else if (msg.what == FreedomHttpListener.EVENT_NETWORD_EEEOR) { callBack.onFailed(); } else if (msg.what == FreedomHttpListener.EVENT_GET_DATA_EEEOR) { callBack.onFailed(); } else if (msg.what == FreedomHttpListener.EVENT_CLOSE_SOCKET) { } callBack.onFinish(); } }
我们可以看到,在消息处理器中传入了一个回调接口类,在不同的返回结果中,触发不同的回调动作。
5、回调接口
package com.example.nettest; /** * @ClassName: FreedomDataCallBack * @author victor_freedom (x_freedom_reddevil@126.com) * @createddate 2015-1-24 下午4:33:38 * @Description: 回调接口,处理返回数据 * @param <T> */ public interface FreedomDataCallBack<T> { public abstract void onStart(); public abstract void processData(T paramObject, boolean paramBoolean); public abstract void onFinish(); public abstract void onFailed(); }
因为我们不知道返回的结果是什么类型的,这里采用泛型来处理
三、http封装后的使用
1、从服务器拿数据的方法
所有的东西我们都已经封装好了之后,该怎么使用呢?我们来尝试写一个方法吧,从服务器获取数据并返回。我们先写一个getDataFromserver的方法在基类中
/** * @Title: getDataFromServer * @Description: 从服务器拿数据 * @param requestType * 请求方式 * @param callBack * 回调接口 * @throws */ protected void getDataFromServer(int requestType, FreedomDataCallBack callBack) { final BaseHandler handler = new BaseHandler(this, callBack); freedomHttpUrlUtils = new FreedomHttpUrlUtils(mContext, new FreedomHttpListener() { @Override public void action(int actionCode, Object object) { Message msg = new Message(); switch (actionCode) { case FreedomHttpListener.EVENT_NOT_NETWORD: msg.what = FreedomHttpListener.EVENT_NOT_NETWORD; break; case FreedomHttpListener.EVENT_NETWORD_EEEOR: msg.what = FreedomHttpListener.EVENT_NETWORD_EEEOR; break; case FreedomHttpListener.EVENT_CLOSE_SOCKET: msg.what = FreedomHttpListener.EVENT_CLOSE_SOCKET; break; case FreedomHttpListener.EVENT_GET_DATA_EEEOR: msg.what = FreedomHttpListener.EVENT_GET_DATA_EEEOR; msg.obj = null; break; case FreedomHttpListener.EVENT_GET_DATA_SUCCESS: msg.obj = object; msg.what = FreedomHttpListener.EVENT_GET_DATA_SUCCESS; break; default: break; } handler.sendMessage(msg); } }, requestType); callBack.onStart(); // 选择不同的请求方法 if (requestType == FreedomHttpUrlUtils.GET_MOTHOD) { freedomHttpUrlUtils.getRequeest(); } else if (requestType == FreedomHttpUrlUtils.POST_MOTHOD) { freedomHttpUrlUtils.postRequest(); } }
2、方法的使用
我们在主Activity中启用一下这个方法。为了方便,博主这里是提交了什么参数就返回什么参数。这里提交的参数统一为username和password形式。请求详细参数请看FreedomHttpUrlUtils中。
我们先看服务端的处理方式:
@Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String parameter = request.getParameter("username"); String parameter2 = request.getParameter("password"); System.out.println(parameter + parameter2); response.setContentType("text/*;charset=utf-8"); response.getWriter().write(parameter + "-" + parameter2); } @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // doGet(request, response); System.out.println("post"); ServletInputStream inputStream = request.getInputStream(); ByteOutputStream b = new ByteOutputStream(); int len = -1; byte[] buf = new byte[1024]; while ((len = inputStream.read(buf)) != -1) { b.write(buf, 0, buf.length); } String s = b.toString(); String[] split = s.split("&"); System.out.println(split[0] + split[1]); response.setContentType("text/*;charset=utf-8"); response.getWriter().write( split[0].substring(split[0].lastIndexOf("=") + 1) + "-" + split[1].substring(split[1].lastIndexOf("=") + 1)); }
我们在看在activity中的调用:
/** * @ClassName: MainActivity * @author victor_freedom (x_freedom_reddevil@126.com) * @createddate 2015-1-24 下午4:40:59 * @Description: TODO */ public class MainActivity extends BaseActivity { private TextView get; private TextView post; @Override protected void findViewById() { get = (TextView) findViewById(R.id.hello); post = (TextView) findViewById(R.id.post); } @Override protected void loadViewLayout() { setContentView(R.layout.activity_main); } @Override protected void processLogic() { } @Override protected void setListener() { } @Override protected void init() { getDataFromServer(1, new FreedomDataCallBack<String>() { @Override public void onStart() { } @Override public void processData(String paramObject, boolean paramBoolean) { get.setText(paramObject); } @Override public void onFinish() { } @Override public void onFailed() { } }); getDataFromServer(2, new FreedomDataCallBack<String>() { @Override public void onStart() { } @Override public void processData(String paramObject, boolean paramBoolean) { post.setText(paramObject); } @Override public void onFinish() { } @Override public void onFailed() { } }); }
我们这里分别采用了两种方法访问,传入参数也是不同的,我们看访问结果,两个textView均显示了访问返回的值。
好了,第一篇关于http访问的文章已经讲解完毕,希望能够帮助到看到此文的人。下一篇我们讲解如何使用httpclient类来实现http网络请求,并实现文件的上传和下载功能。
Android开发之网络请求通信专题(一):基于HttpURLConnection的请求通信
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。