您的位置:首页 > 理论基础 > 计算机网络

okHttp,greenDao,EventBus组合框架项目中实战

2016-03-31 10:00 567 查看
okHttp,greenDao,EventBus组合封装
[align=center]zzyandroid[/align]
介绍

开门见山,大体思路是在Activity中启动服务,通过服务创建Http请求,请求处理结果通过EventBus通知前台更新。

okHttp封装 首先实现下面接口package cn.org.cfpamf.data.i;

import android.support.annotation.NonNull;

import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;

/**
* 项目名称:groupBackstage
* 类描述:
* 创建人:zzy
* 创建时间:2015/10/16 10:14
* 修改人:Administrator
* 修改时间:2015/10/16 10:14
* 修改备注:
*/
public interface IOkHttpRequest {
/**
* 获取HttpClient
* @return
*/
OkHttpClient getOkHttpClient();

/**
* 配置地址
* @return
*/
String getUrl();

/**
* 配置请求
* @return
*/
Request getRequest();

/**
* 配置请求
* @return
*/
Request.Builder getRequestBuilder();

/**
* 处理返回消息
* @return
*/
Callback getResponseCallBack();

/**
* 获取请求主体
* @return
*/
RequestBody getRequestBody();

/**
* 启动网络请求
* @param okHttpClient
* @param request
* @param callback
*/
void execute(@NonNull OkHttpClient okHttpClient, @NonNull Request request, @NonNull Callback callback);
}

然后具体实现:
package cn.org.cfpamf.data.okHttp;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;

import com.orhanobut.logger.Logger;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.concurrent.TimeUnit;

import cn.org.cfpamf.data.exception.e.HandleOkHttpException;
import cn.org.cfpamf.data.exception.e.PrintLog;
import cn.org.cfpamf.data.i.IOkHttpEvent;
import cn.org.cfpamf.data.i.IOkHttpRequest;
import cn.org.cfpamf.data.i.IOkHttpResponse;
import cn.org.cfpamf.data.util.TimeUtils;
import de.greenrobot.event.EventBus;

/**
* 项目名称:groupBackstage
* 类描述:
* 创建人:zzy
* 创建时间:2015/10/20 14:03
* 修改人:Administrator
* 修改时间:2015/10/20 14:03
* 修改备注:
*/
public abstract class AbstractBaseOkHttp implements IOkHttpRequest, IOkHttpResponse, IOkHttpEvent {

private static final String CONTENT_TYPE_KEY = "Content-Type";
protected static final String CONTENT_TYPE = "application/json; charset=utf-8";
private static final String ACCEPT_KEY = "Accept";
private static final String ACCEPT = "application/json";
private static final String UTF8 = "utf8";

private static OkHttpClient okHttpClient;
/**
* get请求参数 Bundle key
*/
public static final String BUNDLE_GET_KEY = "BUNDLE_GET_KEY";
/**
* post/put 请求参数 Bundle key
*/
public static final String BUNDLE_POST_OR_PUT_KEY = "BUNDLE_POST_OR_PUT_KEY";

protected Context context;
protected Bundle bundle;
protected Request request;

/**
* 日志
*/
protected PrintLog printLog;
;
/**
* 网络请求 异常信息
*/
protected String errorMessage;

/**
* @param context
* @param bundle
*/
public AbstractBaseOkHttp(@NonNull Context context, @NonNull Bundle bundle) {
this.context = context;
this.bundle = bundle;
printLog = new PrintLog();
printLog.setRequestTime(TimeUtils.getCurrentTimeInString(new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒")));
request = getRequest();
printLog.setUrl(request.urlString());
printLog.setHeaders(newStringBuilder().append(CONTENT_TYPE_KEY).append("=").append(request.header(CONTENT_TYPE_KEY)).toString());
execute(getOkHttpClient(), getRequest(), getResponseCallBack());
}

/**
* 获取HttpClient
*
* @return
*/
@Override
public OkHttpClient getOkHttpClient() {
if (okHttpClient == null) {
okHttpClient = new OkHttpClient();
} else {
okHttpClient = okHttpClient.clone();
}
okHttpClient.setConnectTimeout(30, TimeUnit.SECONDS);
return okHttpClient;
}

/**
* 请求配置
*
* @return
*/
@Override
public Request.Builder getRequestBuilder() {
return new Request.Builder()
.addHeader(CONTENT_TYPE_KEY, CONTENT_TYPE)
.addHeader(ACCEPT_KEY, ACCEPT);
}

/**
* 处理接口返回
* @return
*/
@Override
public Callback getResponseCallBack() {
return new Callback() {
@Override
public void onFailure(Request request, IOException e) {
onFailed(e);
}

@Override
public void onResponse(Response response) throws IOException {
if (response.isSuccessful())
onSuccess(response);
else
throw new IOException();
}
};
}

/**
* 如果子类需要处理失败信息 重写该方法
*
* @param exception
*/
@Override
public void onFailed(@NonNull Exception exception) {
errorMessage = HandleOkHttpException.handleMessage(exception);
printLogger(errorMessage);
//通知前台更新 失败后返回子类对象 在Activity里注册子类的监听
EventBus.getDefault().post(getPostEvent());
Logger.e(errorMessage);
}

/**
* 启动网络请求
*
* @param okHttpClient
* @param request
* @param callback
*/
@Override
public void execute(OkHttpClient okHttpClient, Request request, Callback callback) {
okHttpClient.newCall(request).enqueue(callback);
}

/**
* 打印日志,写入sd卡并提交腾讯统计服务
*
* @param body
*/
protected void printLogger(String body) {
printLog.setResponseTime(TimeUtils.getCurrentTimeInString(new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒")));
printLog.setResponseBody(body);
printLog.printLogToSdCard(context);
}

public String getErrorMessage() {
return errorMessage;
}

public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}

简单实现后,子类继承即可方便调用,而且少去很多重复代码。下面贴出抽象类后的代码,以请求百度地址为例:

package cn.org.cfpamf.data.okHttp;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;

import com.orhanobut.logger.Logger;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

import java.io.IOException;
import java.util.UUID;

import cn.org.cfpamf.data.database.DatabaseManager;
import cn.org.cfpamf.data.sql.db.Baidu;
import de.greenrobot.event.EventBus;

/**
* 项目名称:Zhnx
* 类描述:
* 创建人:zzy
* 创建时间:2015/11/10 11:00
* 修改人:Administrator
* 修改时间:2015/11/10 11:00
* 修改备注:
*/
public class BaiduTestOkHttp extends AbstractBaseOkHttp {

public static final String TYPE_BAIDU = "BaiduTestOkHttp";

/**
* @param context
* @param bundle
*/
public BaiduTestOkHttp(@NonNull Context context, @NonNull Bundle bundle) {
super(context, bundle);
}

@Override
public AbstractBaseOkHttp getPostEvent() {
return this;
}

@Override
public String getUrl() {
return "Http://www.baidu.com";
}

@Override
public Request getRequest() {
return getRequestBuilder().url(getUrl()).build();
}

/**
* 没有body
*
* @return
*/
@Override
public RequestBody getRequestBody() {
return null;
}

@Override
public void onSuccess(@NonNull Response response) {
try {
String strResponse = response.body().string();
Baidu baiu = new Baidu();
baiu.setId(UUID.randomUUID().toString());
baiu.setResponse(strResponse);
//插入数据库
new DatabaseManager<Baidu>(context).insert(baiu);
//通知前台更新
EventBus.getDefault().post(baiu);
Logger.d(strResponse);
} catch (IOException e) {
onFailed(e);
}
}
}

大家可以看到子类实现可以很简单而且很清晰明了,项目中的日志打印也封装在抽象类中,更是省去了处处调用日志打印的繁琐,
大家注意到里面有个getPostEvent()方法return this,这是为了每个接口失败的返回都通过网络对象通知前台,因为懒得定义新的对象再post通知,
这个例子中成功请求后就往前台通知接口中返回的数据,这样在实际项目中的确是有用的,像前台要知道更新了什么数据,更新了多少条,很容易就实现了。
数据库是在greenDao的基础上抽象出了一个DataBaseManager通过泛型可以简单实现数据中每张表的增删改查。看了下面接口,大家应该就明白了:
package cn.org.cfpamf.data.database;

import java.util.List;

/**
* 项目名称:groupBackstage
* 类描述:
* 创建人:zzy
* 创建时间:2015/8/28 17:05
* 修改人:Administrator
* 修改时间:2015/8/28 17:05
* 修改备注:
*/
public interface IDatabase<M> {

void insert(M m);

void delete(M m);

void insertOrReplace(M m);

void update(M m);

M selectByPrimaryKey(Class<M> entityClass, String Id);

List<M> loadAll(Class<M> entityClass);

void refresh(M m);

/**
* Closing available connections
*/
void closeDbConnections();

/**
* Delete all tables and content from our database
*/
void dropDatabase();

/**
* 事务
*/
void runInTx(Runnable runnable);

}

基本的增删改查是没有问题了。具体启动是通过服务启动的:

package cn.org.cfpamf.data;

import android.app.IntentService;
import android.content.Intent;

import cn.org.cfpamf.data.bus.NetStatusEvent;
import cn.org.cfpamf.data.factory.OkHttpFactory;
import cn.org.cfpamf.data.util.NetWorkUtils;
import de.greenrobot.event.EventBus;

/**
* 项目名称:Zhnx
* 类描述:
* 创建人:zzy
* 创建时间:2015/11/10 10:42
* 修改人:Administrator
* 修改时间:2015/11/10 10:42
* 修改备注:
*/
public class ApiService extends IntentService {

/**
* Creates an IntentService. Invoked by your subclass's constructor.
*/
public ApiService() {
super("ApiService");
}

@Override
public void onCreate() {
super.onCreate();
}

@Override
protected void onHandleIntent(Intent intent) {
if (!NetWorkUtils.isNetworkConnected(getApplicationContext())) {
//在baseActivity里注册即可
EventBus.getDefault().post(newNetStatusEvent(NetStatusEvent.Please_Connect_To_The_Network_And_Try_Again));
} else {
OkHttpFactory.createHttp(this, intent.getType(), intent.getExtras());
}
}

@Override
public void onDestroy() {
super.onDestroy();
}
}

前台所有请求通过调用服务启动,并由IntentService自己管理生命周期,网络处理完毕后即可自己释放掉,而且统一对网络进行判断,通过Bundle携带数据过来,并传递给Http请求。具体Get,post请求源码中有例子,这里就不一一描述,前台接受如下:
package cn.org.cfpamf.zhnx;

import android.widget.TextView;

import butterknife.Bind;
import cn.org.cfpamf.data.base.BaseActivity;
import cn.org.cfpamf.data.manager.StartServiceManager;
import cn.org.cfpamf.data.okHttp.BaiduTestOkHttp;
import cn.org.cfpamf.data.sql.db.Baidu;

public class MainActivity extends BaseActivity {

@Bind(R.id.text_response)
TextView text_response;

@Override
protected void setToolbar() {
}

@Override
protected void setLayoutContentView() {
setContentView(R.layout.activity_main);
}

@Override
protected void afterView() {
StartServiceManager.startBaiduOkHttp(this);
}

/**
* 处理失败信息
*
* @param baiduTestOkHttp
*/
public void onEventMainThread(BaiduTestOkHttp baiduTestOkHttp) {
createHintDialog("失败", baiduTestOkHttp.getErrorMessage());
}

/**
* 处理成功信息
* @param baidu
*/
public void onEventMainThread(Baidu baidu) {
//更新UI
text_response.setText(baidu.getResponse());
}
}

总结这是本人一点点小分享,有兴趣的大家可以下载源码查看,地址是:https://github.com/zzyandroid0425/EXP
源码中还有好多项目中经常用到的东西,比如常见的工具类,常用的BaseRecyclerViewAdapter,AotuGridLayoutManager,也都是自己查询资料,并总结到里面,慢慢的做为一个项目的基础框架使用,后期还会加入android data binding,自己也是准备在现在的项目中去试用这个官方的框架。一起学习。谢谢观看!

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: