最近几个项目,在网络请求上面用的都是同一个Http请求框架,是在项目中搭建出来的,每次想要新开项目的时候,就需要从原来的项目中将好多的文件进行复制粘贴,很容易就出错了,浪费时间,于是我就有了将Http请求框架整合出来,做一个Jar包,方便以后调用。
PS:后面会有这个jar的使用方式,不需要看打包的请直接跳到下面即可
首先,因为这是本人第一次打Jar包并且成功,所以可能很多地方还很生疏,希望多多理解。
我是这么做的。
第一步,新建一个项目,将需要整合出来的相关文件放进这个项目中。不包括资源文件
第二步,右键项目->Export->JAR file
第三步,先把勾选给关闭了,然后勾选src文件夹
第四步,就直接导出即可
导出方式其实很简单,但是需要注意的是,项目中不能有资源文件,因为我这里是纯java代码
如果有资源文件,就不能采用jar包的方式,要采用依赖库
不过好像我之前的文章说过,貌似也有办法,不过还没学会=。=
后面我会尝试依赖库的导出
这篇文章主要还是为了让我能保以记忆
同时贴上我的Http请求jar包下载地址
以及使用方法
将Jar包导入需要使用的项目
建立一个ApiData类
package com.example.crazyandroid.http;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.annotation.SuppressLint;
import com.stanny.xbapidatalibrary.BaseHttpParams;
import com.stanny.xbapidatalibrary.BaseHttpParams.HTTP_MOTHOD;
import com.stanny.xbapidatalibrary.BaseHttpResult;
import com.stanny.xbapidatalibrary.BaseRequestData;
import com.stanny.xbapidatalibrary.CustomException;
import com.stanny.xbapidatalibrary.HttpParam;
import com.stanny.xbapidatalibrary.LogUtil;
public class ApiData extends BaseRequestData<Object, Object, BaseHttpResult> {
public static final int HTTP_ID_getcover = 1;
public static final int HTTP_ID_login = 2;
private HttpParam params = new HttpParam();
public static String baseUrl = "http://192.168.110.8:8080/LJMarketSupervise/";
public static final int FILE_UPLOAD = 999;
public ApiData(int id) {
super(id);
}
public static void setBaseUrl(String ip) {
baseUrl = "http://" + ip + "/LJMarketSupervise/";
}
public void loadData(final Object... objects) {
// if (getId() == HTTP_ID_message_send) {
// super.queueLoadData(objects);
// } else
if (getId() == FILE_UPLOAD) {
final String sqlId = objects[0].toString();
HTTPEXCUTORS.execute(new Runnable() {
String errorMessage = null;
@Override
public void run() {
if (listener != null) {
try {
pHandler.post(new Runnable() {
@Override
public void run() {
listener.onLoadStart(FILE_UPLOAD);
}
});
final BaseHttpResult b = fileUpload(sqlId, (String[]) objects[1]);
if (b.isSuccess()) {
pHandler.post(new Runnable() {
@Override
public void run() {
listener.onLoadComplete(FILE_UPLOAD, b);
}
});
} else {
pHandler.post(new Runnable() {
@Override
public void run() {
listener.onLoadError(FILE_UPLOAD, false, b.getMessage());
}
});
}
} catch (final CustomException e) {
e.printStackTrace();
errorMessage = e.getMessage();
} catch (IOException e) {
e.printStackTrace();
errorMessage = "网络连接失败";
} catch (URISyntaxException e) {
e.printStackTrace();
errorMessage = "网络连接失败";
} catch (JSONException e) {
e.printStackTrace();
errorMessage = "解析失败";
}
if (errorMessage != null) {
pHandler.post(new Runnable() {
@Override
public void run() {
listener.onLoadError(FILE_UPLOAD, false, sqlId);
}
});
}
}
}
});
} else {
super._loadData(objects);
}
}
@Override
protected BaseHttpParams<Object> getHttpParams(int id, Object... objects) {
try {
params.clear();
switch (id) {
case HTTP_ID_login:
params.setApiUrl(baseUrl + "ljClientService.do");
params.setRequestMothod(HTTP_MOTHOD.POST);
params.putParams("method", "login");
params.putParams("loginname", objects[0]);
params.putParams("passwd", objects[1]);
params.putParams("source", "chongqingzxgs_mobile");
break;
// TODO
default:
if (LogUtil.DEBUG) {
LogUtil.e(this, "ApiData请求 id:" + id);
}
break;
}
// if (id != HTTP_ID_login && id != HTTP_ID_ZFYTHlogin) {
// params.putParams("uuid", UUID);
// }
} catch (ArrayIndexOutOfBoundsException e) {
if (LogUtil.DEBUG) {
LogUtil.e(this, "请求参数错误 请检查loadData()是否未带参数");
}
}
return params;
}
@SuppressLint("SimpleDateFormat")
@Override
protected BaseHttpResult parseStr(int id, String currentDownloadText, BaseHttpResult lastData) throws Exception {
JSONObject list;
JSONObject jsonObject = null;
BaseHttpResult result = new BaseHttpResult();
switch (id) {
/** api */
default:
try {
jsonObject = new JSONObject(currentDownloadText);
} catch (Exception e) {
result.setSuccess(false);
return result;
}
String msg;
String code = getStringValue(jsonObject, "code");
msg = getStringValue(jsonObject, "message");
result.setMessage(msg);
result.setSuccess("0".equals(code) || "20000".equals(code));
if (result.isSuccess()) {
switch (id) {
case HTTP_ID_login: {
result.setEntry(jsonObject);
}
break;
// TODO
default:
break;
}
}
break;
}
return result;
}
public JSONObject getJSONObject(JSONObject jsonObject, String name) {
try {
return jsonObject.getJSONObject(name);
} catch (JSONException e) {
e.printStackTrace();
return new JSONObject();
}
}
public JSONArray getJSONArray(JSONObject jsonObject, String name) {
try {
return jsonObject.getJSONArray(name);
} catch (JSONException e) {
e.printStackTrace();
return new JSONArray();
}
}
public String getStringValue(JSONObject jsonObject, String name) {
try {
if (jsonObject.getString(name).equals("null")) {
return "";
} else {
return jsonObject.getString(name);
}
} catch (JSONException e) {
e.printStackTrace();
return "";
}
}
public int getIntValue(JSONObject jsonObject, String name) {
try {
return jsonObject.getInt(name);
} catch (JSONException e) {
e.printStackTrace();
return 0;
}
}
public double getDoubleValue(JSONObject jsonObject, String name) {
try {
return jsonObject.getDouble(name);
} catch (Exception e) {
return 0;
}
}
/**
*
* @return
* @throws IOException
* @throws URISyntaxException
* @throws CustomException
* @throws JSONException
*/
private BaseHttpResult fileUpload(String id, String[] paths) throws IOException, URISyntaxException, CustomException, JSONException {
BaseHttpResult result = new BaseHttpResult();
HttpEntity httpEntity = null;
HttpPost httpPost = new HttpPost(baseUrl + "eventfileUpload");
MultipartEntity multipartEntity = new MultipartEntity();
for (int i = 0; i < paths.length; i++) {
File file = new File(paths[i]);
if (!file.exists()) {
throw new FileNotFoundException(paths[i] + " is not found!!!");
}
ContentBody contentBody = new FileBody(file, URLEncoder.encode(file.getName(), "utf-8"), "application/octet-stream", "utf-8");
// ContentBody contentBody = new FileBody(file);
multipartEntity.addPart("filedata", contentBody);
}
// multipartEntity
// .addPart("user_id", new StringBody(map.get("user_id"),
// Charset.forName("UTF-8")));
httpPost.setEntity(multipartEntity);
BasicHttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 50000);
HttpConnectionParams.setSoTimeout(httpParams, 50000);
HttpClient httpClient = new DefaultHttpClient(httpParams);
InputStream inputStream = null;
HttpResponse httpResponse = null;
try {
if (LogUtil.DEBUG) {
LogUtil.e(this, "开始上传");
}
httpResponse = httpClient.execute(httpPost);
if (LogUtil.DEBUG) {
LogUtil.e(this, "上传相应完成 HttpCode:" + httpResponse.getStatusLine().getStatusCode());
}
if (httpResponse.getStatusLine().getStatusCode() == 200) {
httpEntity = httpResponse.getEntity();
inputStream = httpEntity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line = null;
String cont = "";
while ((line = reader.readLine()) != null) {
cont += line;
}
if (LogUtil.DEBUG) {
LogUtil.e(this, "上传返回信息:" + cont);
}
JSONObject json = new JSONObject(cont);
result.setSuccess("0".equals(getStringValue(json, "code")));
result.setMessage(getStringValue(json, "message"));
result.setEntry(getStringValue(json, "data"));
} else {
listener.onLoadError(FILE_UPLOAD, false, "上报失败");
throw new CustomException("上传失败:" + httpResponse.getStatusLine().getStatusCode());
}
} catch (Exception e) {
return result;
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
// private List<TaskCountInfo> parseCount(JSONObject list, String name) {
// List<TaskCountInfo> taskList = new ArrayList<TaskCountInfo>();
// try {
// JSONArray dataList = getJSONArray(list, name);
// for (int i = 0; i < dataList.length(); i++) {
// TaskCountInfo taskEntity = new Gson().fromJson(dataList.getString(i), TaskCountInfo.class);
// taskList.add(taskEntity);
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
// return taskList;
// }
}
代码比较乱,各位看的时候多看看,其中最总要的是两个地方
switch (id) {
case HTTP_ID_login:
params.setApiUrl(baseUrl + "ljClientService.do");
params.setRequestMothod(HTTP_MOTHOD.POST);
params.putParams("method", "login");
params.putParams("loginname", objects[0]);
params.putParams("passwd", objects[1]);
params.putParams("source", "chongqingzxgs_mobile");
break;
// TODO
default:
if (LogUtil.DEBUG) {
LogUtil.e(this, "ApiData 请求 id:" + id);
}
break;
}
这里包括了所有的HTTP请求的请求参数,每次多一个就添加一个即可
if (result.isSuccess()) {
switch (id) {
case HTTP_ID_login: {
result.setEntry(jsonObject);
}
break;
// TODO
default:
break;
}
}
这里包括了所有的HTTP请求返回参数,可以在这里获得所有的请求返回
举例:
比如我现在要添加调用一个新的接口比如获取用户列表,首先在ApiData中,新建一个常量
public static final int HTTP_ID_getUserList = 5;//这些都随意的
然后在
getHttpParams
这个方法中的swich中添加一个新的case,例如
case HTTP_ID_countPolyBySummaryId:
params.setApiUrl(baseUrl + "AppStatisController.do");
params.setRequestMothod(HTTP_MOTHOD.POST);
params.putParams("method", "appCountTaskByRecode");
params.putParams("reviewId", objects[0]);
params.putParams("isRecord", objects[1]);
break;
setApiUrl
是设置请求的地址
setRequestMothod
是设置请求的方式,post、get
putParams
就是设置请求的参数呢,这里有个object[0]这种格式的东西,后面会提到现在先不说
这样我们的请求就算可以了,然后就是获取返回了
在
parseStr
这个方法里面的case处书写获取到返回的处理方法
我这里获取的是一个jsonobject
比如登录返回
case HTTP_ID_login:
jsonObject = getJSONObject(jsonObject, "data");
TOKEN = getStringValue(jsonObject, "token");
HttpLoginEntity loginEntity = new HttpLoginEntity();
loginEntity.setfGender(getStringValue(jsonObject, "fGender"));
loginEntity.setfDuty(getStringValue(jsonObject, "fDuty"));
loginEntity.setfRegionCode(getStringValue(jsonObject, "fRegionCode"));
loginEntity.setfUserName(getStringValue(jsonObject, "fUserName"));
loginEntity.setfUserId(getStringValue(jsonObject, "fUserId"));
loginEntity.setfDepartment(getStringValue(jsonObject, "fDepartment"));
loginEntity.setfDesc(getStringValue(jsonObject, "fDesc"));
loginEntity.setfAge(getStringValue(jsonObject, "fAge"));
loginEntity.setfUserType(getStringValue(jsonObject, "fUserType"));
loginEntity.setfRealName(getStringValue(jsonObject, "fRealName"));
loginEntity.setfTelephone(getStringValue(jsonObject, "fTelephone"));
loginEntity.setUserRole(jsonObject.getJSONArray("userRole").getString(0));
result.setEntry(loginEntity);
break;
可以很清楚的看到这里使用了实体类对返回数据进行了存储,最后
result.setEntry(loginEntity);
将拼装好的实体类进行一个返回,返回支持各种类型,String、boolean等都可以,返回使用的地方,下面会提到的
另外,可以看到里面有
getStringValue(jsonObject, "fDesc")
这样的方法,类似的里面有五个这样的方法
getStringValue(jsonObject, "fDesc")
分别是
getStringValue、getIntValue、getDoubleValue、getJsonObject、getJsonArray
这是我特意封装为了防止返回的参数为空而引起的错误,这五个方法就在我的ApiData的最下面
好这样我们的一个网络接口请求就算实现好了,接下来就是如何使用
在我们需要进行请求的Activity、Fragment等地方
我们用类去实现一个监听器
public class HttpTestActivity extends Activity implements OnHttpLoadingListener<BaseHttpResult>{
实现后,会需要实现三个接口
@Override
public void onLoadComplete(int id, BaseHttpResult b) {
((TextView)findViewById(R.id.tv_apiTest)).setText((String)b.getEntry());
}
@Override
public void onLoadError(int id, boolean bool, String error) {
}
@Override
public void onLoadStart(int id) {
}
很容易就可以知道,分别是请求成功、请求失败、请求开始
我们可以在请求开始的时候,弹出一个dialog,显示一个正在加载的Progress进度条
在请求失败和请求成功的时候取消dialog即可
可以在请求失败的方法里获取失败信息
最后就是请求成功的处理方法了
我代码里有一个简单的使用方式
(String)b.getEntry()
前面说过b可以是各种类型的参数,这里只需要进行强制转换成我们需要的类型即可。
比如刚刚我们传过来一个实体类,这里只需要强制转换成该实体类,就可以进行使用了
假如这个类中我们同时调用了多个Http请求,只需要在方法里用switch-case,根据ID类判断是哪一个即可,比如
switch (id) {
case ApiData.HTTP_ID_getPolygonListByPackId:
if (b.isSuccess()) {
polygonListEntity = (PolygonListEntity) b.getEntry();
if (null != polygonListEntity && null != polygonListEntity.getInfoEntities()) {
mTotalNo = polygonListEntity.getTotal();
mTaskList.clear();
mTaskList.addAll(polygonListEntity.getInfoEntities());
polygonListEntity.setHttpPackInfoEntity(mPackInfo);
((PolygonListActivity) getActivity()).polygonListMap.put(mTaskStatus, polygonListEntity);
mTaskAdapter.notifyDataSetChanged();
mLvContent.smoothScrollToPosition(0);
}
if (mPageNo * mPageSize < mTotalNo) {
mLvContent.mFooterView.show(mPageNo,mTotalNo/mPageSize+1);
} else {
mLvContent.mFooterView.hide();
}
loadCount();
}
break;
case ApiData.HTTP_ID_getTaskPackageList:
if (b.isSuccess()) {
httpPacksListEntity = (HttpPacksListEntity) b.getEntry();
dataList.clear();
if (null != httpPacksListEntity && null != httpPacksListEntity.getHttpPackInfoEntities()) {
for (int i = 0; i < httpPacksListEntity.getHttpPackInfoEntities().size(); i++) {
HttpPackInfoEntity entity = httpPacksListEntity.getHttpPackInfoEntities().get(i);
KeyValueInfo keyValueInfo = new KeyValueInfo(entity.getfPackCode(), entity.getfPackId());
dataList.add(keyValueInfo);
}
}
adapter = new ArrayAdapter<KeyValueInfo>(getActivity(), android.R.layout.simple_spinner_dropdown_item, dataList);
sp_parakgeCheckList.setAdapter(adapter);
loadCount();
}
break;
case ApiData.HTTP_ID_addPolygonIntoPack:
if (b.isSuccess()) {
loadData();
loadCount();
}
break;
case ApiData.HTTP_ID_getPackAndSubviewCount:
if (b.isSuccess()) {
TaskCountEntitiy countEntitiy = (TaskCountEntitiy) b.getEntry();
fragment.setRBtnText("left", countEntitiy.getWeiChuLi());
fragment.setRBtnText("mid", countEntitiy.getWg());
fragment.setRBtnText("right", countEntitiy.getNotWg());
fragment.setRBtnText("all", countEntitiy.getWeiChuLi() + countEntitiy.getWg() + countEntitiy.getNotWg());
}
break;
default:
break;
这里是顺手贴的我的代码
好处理写好了,然后是如何进行请求了
很简单,只需要在该类中,声明一个对应的接口
<span style="white-space:pre"> </span>private ApiData getPolygonListById = new ApiData(ApiData.HTTP_ID_getPolygonListByPackId);
private ApiData getPackageList = new ApiData(ApiData.HTTP_ID_getTaskPackageList);
private ApiData addPolyIntoPack = new ApiData(ApiData.HTTP_ID_addPolygonIntoPack);
private ApiData getPackAndSubviewCount = new ApiData(ApiData.HTTP_ID_getPackAndSubviewCount);
比如这样,我们根据ApiData中的各个常量来声明对应的接口即可(常量在ApiData中已经与相关接口对应了,详情见上文)
然后在Oncreate的时候声明一个监听器
<span style="white-space:pre"> </span>getPolygonListById.setLoadingListener(this);
getPackageList.setLoadingListener(this);
addPolyIntoPack.setLoadingListener(this);
getPackAndSubviewCount.setLoadingListener(this);
最后,在你需要调用接口的地方,用刚刚声明的ApiData类型的参数调用即可
getPolygonListById.loadData(mPackInfo.getfPackId(), mPageNo, mPageSize, 1, 0, mPdJG);
loadData中支持各种类型,不限数量,但是需要注意了,这里的顺序和你请求的时候取得顺序必须一致
前面提到过object[0]、object[1]这种
这里的object[0]就是指的loadData()里面的第一个参数,一一对应即可
到这里,整个流程就结束呢
这样我们只需要一个ApiData类就包含了所有的网络请求和返回,在修改,查看,调试等方面都有了很好的帮助
希望大家喜欢,有什么问题在下面留言即可
PS:友情提示,可以让BaseActivity、BaseFragment去实现
OnHttpLoadingListener<BaseHttpResult>
这样在Base类中把加载失败和加载开始进行处理了,在继承了Base类的其他类中,只需要处理加载成功即可
PSS:本方法还实现了文件的上传和下载,详情可以看看ApiData中的文件,这里就不一一说了
PSSS:ApiData中还提供了
setBaseUrl
这个方法,用于更改URL地址,在需要经常变换IP的情况下可以使用,其他情况,可以无视或删除
PSSSS:ApiData可能还需要导入一个httpmine-4.1.1.jar,否则文件上传那里会有点错误,不需要文件上传的请无视