Android之利用volley搭建简洁网络框架

Android之利用volley搭建简洁网络框架

文章链接:

知识点:

  1. 为什么一定要联网操作;
  2. 利用volley搭建合适自己的简介网络请求框架;
  3. 新名词记录{枚举;手动解析json}

概述

在当今互联网大潮中,中国的网络已经很普及了,互联网已经不是一个新鲜的词语。我们也是搭上了互联网快车,而且是移动互联网这一节车厢。
如今,在进行APP开发中,使用网络请求数据已经是每个APP必备的内容了。我敢说是一定有的,因为你不需要为用户提供账号系统和存储等,至少都要“收集用户信息”,你的APP被每一位用户握在手里,这是最快捷触达用户的途径了。

“用户为中心”一直是我们公司的的口号之一。那么要了解用户,就需要获取用户的各种信息,才能够更加好的“运营用户”。

所以,这里是总结:每一个APP都需要进行联网。

如果没有联网操作的APP,那就是在耍流氓了。没有谁会丢这么一个APP到用户手里吧?!

完。。。。。。


打造联网框架

俗话说:我们要站在巨人的肩膀上。联网的巨人之一就是volley。如果大家对volley还不熟悉,可以去百度,里面大把的教程。我这里对其进行封装,打造自己的简单易用的网络框架。

我已经将代码注释的很清楚了。各位看官慢慢品尝。

第一步:实体基类 AbsBaseBean.java

package com.yaojt.sdk.java;

import com.yaojt.sdk.java.utils.CommonLog;

import org.json.JSONObject;

import java.io.Serializable;

/**
 * desc:基类basebean
 * 

* author:kuyu.yaojt (tanksu) *

* email:[email protected] *

* blog:http://blog.csdn.net/qq_16628781 *

* date:17/4/9 */ public abstract class AbsBaseBean implements Serializable { private String TAG = AbsBaseBean.class.getSimpleName(); /** * 请求成功码 */ public final String SUCCESS_CODE = "0"; /** * 系统错误,返回码 */ public final String SYSTEM_ERROR_CODE = "-1"; /** * 密码错误返回码 */ public final String INVALID_PARAMS_CODE = "1"; /** * token不可用返回码 */ private final String EMPTY_TOKEN_CODE = "-3"; /** * 需要重新登录的返回码 */ private final String LOGOUT_CODE = "-4"; private String code; private String message; private String sign; private String decodeData; private String originalData; ResponseStatus mResponseStatus; /** * 解析返回的数据 * * @param response 返回的数据 */ public void parseResponse(String response) { if (response == null || response.equals("")) { mResponseStatus = ResponseStatus.RESPONSE_EXCEPTION; return; } try { JSONObject jsonObject = new JSONObject(response); code = jsonObject.optString("code"); message = jsonObject.optString("message"); mResponseStatus = SUCCESS_CODE.equals(code) ? ResponseStatus.SUCCESS : (SYSTEM_ERROR_CODE.equals(code) ? ResponseStatus.SERVICE_EXCEPTION : ResponseStatus.PARAMS_EXCEPTION); //检查是否被挤下线 if (LOGOUT_CODE.equals(code) || EMPTY_TOKEN_CODE.equals(code)) { mResponseStatus = ResponseStatus.LOGOUT; //下线处理后续操作 } originalData = jsonObject.optString("data"); if (null == originalData || "null".equals(originalData) || "".equals(originalData)) { mResponseStatus = ResponseStatus.PARAMS_EXCEPTION; //toast提示 return; } //如果有传输加密,对数据进行解密 //decodeData = EncryptUtil.doubleDecrypt(originalData); decodeData = originalData; CommonLog.logInfo("decodeData", decodeData); if ("[]".equals(decodeData) || "{}".equals(decodeData)) { mResponseStatus = ResponseStatus.PARAMS_EXCEPTION; //ToastUtils.makeText(MyApplication.getInstance(), message, ToastUtils.ONE_SECOND); return; } //手动解析数据 parseData(originalData, decodeData); } catch (Exception e) { mResponseStatus = ResponseStatus.OTHER_ERROR; e.printStackTrace(); } } /** * data数据体 * * @param orign 原始数据 * @param decode 解密数据 */ public abstract void parseData(String orign, String decode); /** * 从JSON中取key对应的值,无值是返回默认值 * * @param object JSONObject * @param key 值对应的key * @param defaultValue 默认值 * @return value 如果有对应的key,则返回对应的值,反之返回defaultValue */ protected String getStringFromJsonObject(JSONObject object, String key, String defaultValue) { if (null == object || null == key) return defaultValue; return object.has(key) ? object.optString(key) : defaultValue; } /** * 返回结果状态 */ public enum ResponseStatus { /** * 成功 */ SUCCESS, /** * 返回数据异常 */ RESPONSE_EXCEPTION, /** * 网络连接失败 */ NETWORK_ERROR, /** * 服务异常 */ SERVICE_EXCEPTION, /** * 参数异常 */ PARAMS_EXCEPTION, /** * 其他 错误 */ OTHER_ERROR, /** * 登录过期 */ LOGOUT } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public String getSign() { return sign; } public void setSign(String sign) { this.sign = sign; } public String getDecodeData() { return decodeData; } public void setDecodeData(String decodeData) { this.decodeData = decodeData; } public String getOriginalData() { return originalData; } public void setOriginalData(String originalData) { this.originalData = originalData; } public ResponseStatus getmResponseStatus() { return mResponseStatus; } public void setmResponseStatus(ResponseStatus mResponseStatus) { this.mResponseStatus = mResponseStatus; } }

上面的代码主要有几点:
1. 你需要一个volley.jar的包;
2. 定义一系列的请求返回码(需要和后台商定);
3. 定义一个请求异常枚举(ResponseStatus);
4. parseResponse(String response)方法对原始的数据进行处理:如果没有加密,直接从json中获取到数据;如果有加密,需要进行解密之后才进行操作;最后调用parseData()方法进行手动解析数据,所以要求所有的实体类都要继承此基本实体类;此类只是对共有的几个属性值和结果进行判断,将具体的操作给到子类进行处理;
5. 一些基本的setter,getter方法;


第二步:进行网络封装

在这里,实现默认已经加入volley的代码。
因为我们就是使用volley进行网络请求处理的。

我们这里主要是利用volley进行< JSONObject>请求,因为绝大多数的网络传输都是使用json。我们这里也不例外,不过项目里面对数据进行了aes+des双重加密。

具体代码如下所示:JsonRequestImpl.java

package com.yaojt.sdk.java.network;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.toolbox.HttpHeaderParser;
import com.yaojt.sdk.java.utils.CommonLog;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * desc:自定义请求,利用map传參
 * 

* author:kuyu.yaojt (tanksu) *

* email:yaojt@kuyumall.com *

* blog:http://blog.csdn.net/qq_16628781 *

* date:17/4/9 */ public class JsonRequestImpl extends Request<JSONObject> { private Map mMap; private Response.Listener mListener; //private AppSharedPreferences appSharedPreferences; /** * 构造方法 * * @param url 请求地址 * @param listener 成功监听器 * @param errorListener 错误监听器 * @param map 入参数据 */ public JsonRequestImpl(int method, String url, Response.Listener listener, Response.ErrorListener errorListener, Map map) { super(Request.Method.POST, url, errorListener); mListener = listener; mMap = map; this.method = method; } private int method; @Override public Map getHeaders() throws AuthFailureError { return addHeaders(method == 1 ? "POST" : (method == 2 ? "PUT" : "GET") + "-Header"); } /** *

  • 请求header
  • * * @param tag 日志标记请求类型 * @return headers */
    protected Map addHeaders(String tag) { Map header = new HashMap<>(); //String accessToken = new AppSharedPreferences(MyApplication.getInstance()).getAccessToken(); String accessToken = "123456789"; String str = null; try { String byteStr = new String(accessToken.getBytes(), "utf-8"); str = URLEncoder.encode(byteStr, "utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } header.put("login-token", str); //带入token CommonLog.logInfo(tag, header.toString()); return header; } @Override protected Response parseNetworkResponse(NetworkResponse networkResponse) { try { String jsonStr = new String(networkResponse.data, HttpHeaderParser.parseCharset(networkResponse.headers)); return Response.success(new JSONObject(jsonStr), HttpHeaderParser.parseCacheHeaders(networkResponse)); } catch (UnsupportedEncodingException | JSONException e) { e.printStackTrace(); } return null; } @Override protected void deliverResponse(JSONObject jsonObject) { if (null != mListener) mListener.onResponse(jsonObject); } //mMap是已经按照前面的方式,设置了参数的实例 @Override protected Map getParams() throws AuthFailureError { return mMap; } }

    说明:
    1. 传入必要的参数URL,入参,成功监听和失败监听;
    2. 请求的头部加入信息,例如token等等;


    第三步:便捷使用

    下面这个使用类就比较简单了。

    package com.yaojt.sdk.java.network;
    
    import android.content.Context;
    
    import com.android.volley.toolbox.Volley;
    import com.yaojt.sdk.java.AbsBaseBean;
    import com.yaojt.sdk.java.i.RequestCallBack;
    
    import java.util.Map;
    
    /**
     * desc:sdk中的网络请求处理类
     * 注意:这里有一个问题,当用户传入的是activity的context,会造成内存泄漏
     * 所以建议将此类卸载可以引用application的module下面
     * 

    * author:kuyu.yaojt (tanksu) *

    * email:[email protected] *

    * blog:http://blog.csdn.net/qq_16628781 *

    * date:17/4/9 */ public class HttpRequestHandler extends AbsHttpRequest { protected static final String DEVICE = "Android"; protected static final String VERSION = "1.0"; private static HttpRequestHandler sVolleyHandler; /** * 构造函数私有化 */ private HttpRequestHandler(Context context) { super(); mRequestQueue = Volley.newRequestQueue(context); } /** * 网络请求单例模式 * * @return VolleyHandler */ public static HttpRequestHandler getInstance(Context context) { if (sVolleyHandler == null) { synchronized (HttpRequestHandler.class) { if (sVolleyHandler == null) { sVolleyHandler = new HttpRequestHandler(context); } } } return sVolleyHandler; } /** * post json请求 * * @param url 请求链接地址 * @param params post请求参数 * @param baseModel BaseModel * @param callBack TaskCallBack */ public void postJsonRequest(Context context, String url, final Map params, final AbsBaseBean baseModel, final RequestCallBack callBack) { super.postJsonRequest(context, url, params, baseModel, callBack); } @Override protected boolean checkNetworkVisiable() { //网络检查操作 return true; } }

    说明:
    1. 使用单例并加锁的方式保证单例唯一性和安全性;
    2. 提供一个post方式的网络请求方法给外部调用;
    3. 网络检查部分代码没有实现,需要自己去实现;

    注意:这里有一个问题,当用户传入的是activity的context,会造成内存泄漏所以建议将此类卸载可以引用application的module下面。我这里使用的是sdk的一个module,不能够直接应用application的实现类。

    总结

    上面的使用方式很简介,对于网络请求的底层,例如线程、线程池等等,volley都做了比较好的封装,我们只管上层的调用开发,不用关注细节。

    当然,也有不好的,我们毕竟还是需要知道线程的创建和使用等等的知识。这一块是进阶的必备功课。接下来我也会新开一篇文章,讲解利用最原始的方式进行网络请求框架的搭建和使用。

    以上就是所有内容,如有任何问题,请及时与我联系,谢谢。

    你可能感兴趣的:(android网络)