AutoNet (網(wǎng)絡(luò)框架)
AutoNet 代理了OkHttp滤灯, 處理了復(fù)雜繁瑣的網(wǎng)絡(luò)請求代碼巧娱! 使Android開發(fā)網(wǎng)絡(luò)應(yīng)用更加簡單赌躺,只需關(guān)注業(yè)務(wù)即可。
Git地址
1.Android版本:
2.ios版本:
AutoNet 技術(shù)交流群:
QQ: 141027175
Demo說明
- app: AutoNet各個方式使用介紹
- recommendeddemo: AutoNet推薦用法(注:Api使用了wanandroid的Api)
特色
- 使用簡單徐勃、調(diào)用方便
- 支持了同步事示、異步操作
- 支持注解、 鏈?zhǔn)?/li>
- 支持實體類僻肖、map傳值
- 可防止內(nèi)存泄漏(需繼承RxFragmentActivity肖爵、或者RxFragment。并向AutoNet傳入相應(yīng)的生命周期)
- 可動態(tài)添加和修改頭部
- 可對請求參數(shù)數(shù)據(jù)進(jìn)行加密
- 可自主處理返回的頭部數(shù)據(jù)
- 可自主處理返回的body數(shù)據(jù)
- 可自定義返回數(shù)據(jù)的類型
- 可定義固定臀脏、靈活及臨時的域名劝堪、頭部信息(優(yōu)先級: 臨時>靈活>固定。 有效性: 固定 >= 靈活 > 臨時)
- 支持網(wǎng)絡(luò)策略(網(wǎng)絡(luò)揉稚、本地秒啦、先本地后網(wǎng)絡(luò)、先網(wǎng)絡(luò)后本地)
- 支持上傳文件和下載文件
- 可直接獲得上游的Flowable, 用戶自己進(jìn)行操作結(jié)果搀玖。(eg: 使用zip去合并多個請求等)
gradle依賴
compile 'cn.xiaoxige:autonet-api:2.0.3'
annotationProcessor 'cn.xiaoxige:autonet-processor:2.0.3'
簡易使用demo
AutoNet_Android.png
使用
1. 初始化
1.1 AutoNetConfig(配置AutoNet的基本配置)注意:改配置基本是固定余境,如域名、頭部數(shù)據(jù)
- 設(shè)置是否開啟Stetho調(diào)試配置
- 設(shè)置默認(rèn)域名(key: default)
- 設(shè)置多個域名
- 設(shè)置頭部參數(shù)
- 設(shè)置Okhttp的攔截器
1.2 AutoNet的初始化操作
AutoNet.getInstance().initAutoNet(Context, AutoNetConfig);
可以鏈?zhǔn)饺ピO(shè)置加密的回調(diào)巷怜,頭部數(shù)據(jù)的回調(diào)葛超,Body數(shù)據(jù)的回調(diào), eg:
AutoNet.getInstance().initAutoNet(Context, AutoNetConfig)
.setEncryptionCallback(new IAutoNetEncryptionCallback() {
@Override
public String encryption(Long key, String encryptionContent) {
// 可通過key去加密參數(shù)
return encryptionContent;
}
}).setHeadsCallback(new IAutoNetHeadCallBack() {
@Override
public void head(Object flag, Headers headers) {
// 請求返回的頭部數(shù)據(jù)回調(diào)
}
}).setBodyCallback(new IAutoNetBodyCallBack() {
@Override
public boolean body(Object flag, String body) throw Exception {
// 自己處理需要返回true
return false;
}
});
還可以再次設(shè)置域名和頭部數(shù)據(jù)(這里的配置為靈活的, 可在任意地方修改)
AutoNet.getInstance().updateOrInsertHead(key, value);
AutoNet.getInstance().updateOrInsertDomainNames(key, value);
2. 支持清單
2.1. 支持請求類型方式及策略
. | 請求類型 | 請求方式 | 策略 |
---|---|---|---|
注解方式 | GET/POST/DELETE/PUT | JSON/FORM/STREAM | NET/LOCAL_NET/LOCAL/NET_LOCAL |
鏈?zhǔn)酵?/td> | GET/POST/DELETE/PUT | JSON/FORM/STREAM | NET/LOCAL |
獲取上游發(fā)射器 | GET/POST/DELETE/PUT | JSON/FORM/STREAM | NET/LOCAL |
鏈?zhǔn)疆惒剑ㄍ扑]) | GET/POST/DELETE/PUT | JSON/FORM/STREAM | NET/LOCAL_NET/LOCAL/NET_LOCAL |
2.2. 支持的回調(diào)
. | 注解方式 | 鏈?zhǔn)酵?/th> | 獲取上游發(fā)射器 | 鏈?zhǔn)疆惒剑ㄍ扑]) |
---|---|---|---|---|
IAutoNetBodyCallBack | ? | ? | ? | ? |
IAutoNetHeadCallBack | ? | ? | ? | ? |
IAutoNetEncryptionCallback | ? | ? | ? | ? |
AbsAutoNetCallback | ? | ? | ? | ? |
IAutoNetCallBack | ? | ? | ? | ? |
IAutoNetComplete | ? | ? | ? | ? |
IAutoNetDataBeforeCallBack | ? | ? | ? | ? |
IAutoNetDataSuccessCallBack | ? | ? | ? | ? |
IAutoNetDataCallBack | ? | ? | ? | ? |
IAutoNetFileCallBack | ? | ? | ? | ? |
IAutoNetLocalOptCallBack | ? | ? | ? | ? |
3. 回調(diào)介紹
回調(diào)需要繼承實現(xiàn)AutoNet提供好的接口或者抽象類延塑。AutoNet已經(jīng)分類, 用戶需要什么功能就去集成相應(yīng)的接口或者抽象類即可
3.1 IAutoNetDataBeforeCallBack(數(shù)據(jù)返回前的處理答渔, 可定制要繼續(xù)返回給客戶前端的數(shù)據(jù))
public interface IAutoNetDataBeforeCallBack<T, Z> extends IAutoNetCallBack {
// T為用戶指定的body要返回的實體類(AutoNet會自動轉(zhuǎn)換)关带, emitter為Rxjava的上游, 可改變其返回結(jié)果。 如果自己處理需要返回true宋雏。eg: T為一個實體類芜飘, 里面有一個List集合, 我們在View層只需要關(guān)注List集合磨总,則可以在這里直接重新定義并返回List集合嗦明, 并返回true。 (注意:其實這里還有一個功能就是蚪燕, 根據(jù)自己的需求去判斷是否集合為空更妙娶牌。emitter.onError(new EmptyError())。)
boolean handlerBefore(T t, FlowableEmitter<Z> emitter);
}
3.2 IAutoNetDataSuccessCallBack(只關(guān)心成功的數(shù)據(jù)馆纳, 不關(guān)心失敗和數(shù)據(jù)為空的結(jié)果)
public interface IAutoNetDataSuccessCallBack<T> extends IAutoNetCallBack {
// T為用戶需要返回的實體類
void onSuccess(T entity);
}
3.3 IAutoNetDataCallBack(數(shù)據(jù)返回比較全的回調(diào), 包含了數(shù)據(jù)成功诗良、數(shù)據(jù)失敗、數(shù)據(jù)為空)
public interface IAutoNetDataCallBack<T> extends IAutoNetDataSuccessCallBack<T> {
// 失敗
void onFailed(Throwable throwable);
// 數(shù)據(jù)為空(注意:如果不在IAutoNetDataBeforeCallBack去根據(jù)自己的業(yè)務(wù)去手動拋出emitter.onError(new EmptyError())的話鲁驶, AutoNet是不知道你的業(yè)務(wù)是什么的鉴裹, 所以在這個情況下AutoNet在body都為空的時候才調(diào)用onEmpty())
void onEmpty();
}
3.4 IAutoNetLocalOptCallBack(需要用到本地操作, eg:網(wǎng)絡(luò)策略钥弯, 本地径荔、 先本地后網(wǎng)絡(luò), 先網(wǎng)絡(luò)后本地脆霎。 其實AutoNet并不能自動根據(jù)你的業(yè)務(wù)和字段給你建立數(shù)據(jù)庫猖凛, 需要自己去實現(xiàn))
public interface IAutoNetLocalOptCallBack<T> extends IAutoNetCallBack {
T optLocalData(Map request) throws Exception;
}
3.5 IAutoNetFileCallBack(文件操作時的回調(diào), 需要關(guān)心上傳錯誤等需要繼承上面的IAutoNetDataCallBack)
public interface IAutoNetFileCallBack extends IAutoNetCallBack {
// 上傳文件或者下載文件的進(jìn)度(0~100)
void onPregress(float progress);
// 上傳成功或者下載成功后的File文件回調(diào)
void onComplete(File file);
}
3.6 IAutoNetComplete (請求結(jié)束后绪穆, 該回調(diào)會被調(diào)用辨泳,不管錯誤成功后都會調(diào)用)
public interface IAutoNetComplete extends IAutoNetCallBack {
void onComplete();
}
3.7 AbsAutoNetCallback(數(shù)據(jù)回調(diào)的集合, 其實數(shù)據(jù)寫這個就行了玖院, 需要什么方法重寫什么方法即可)
// 其中 T為返回的body的實體類菠红,Z為自己處理后需要返回給View層后的實體類
public abstract class AbsAutoNetCallback<T, Z> implements IAutoNetDataBeforeCallBack<T, Z>, IAutoNetDataCallBack<Z>, IAutoNetComplete {
@Override
public boolean handlerBefore(T t, FlowableEmitter<Z> emitter) {
return false;
}
@Override
public void onSuccess(Z entity) {
}
@Override
public void onFailed(Throwable throwable) {
}
@Override
public void onEmpty() {
}
@Override
public void onComplete() {
}
}
}
4. 鏈?zhǔn)秸{(diào)用
AutoNet.getInstance().createNet()
// 設(shè)置url后綴(除去域名)
.setSuffixUrl(String)
// 設(shè)置一個標(biāo)志, 會在全局的Head和Body中回調(diào)
.setFlag(flag)
// 參數(shù)
.setParams(Map)
.setParam(key, value)
.setRequestEntity(IAutoNetRequest)
// post請求(可傳參數(shù))
.doPost(...)
// get請求(可傳參數(shù))
.doGet(...)
// put(可傳參數(shù))
.doPut(...)
// delete(可傳參數(shù))
.doDelete(...)
// 指定使用的域名的Key(默認(rèn)default)
.setDomainNameKey(String)
// 設(shè)置網(wǎng)絡(luò)請求方式
.setNetPattern(NetPattern)
// 設(shè)置網(wǎng)絡(luò)策略
.setNetStrategy(NetStrategy)
// 設(shè)置請求類型(JSON/FORM/STREAM/OTHER)
.setReqType(Type)
// 設(shè)置返回類型(JSON/FORM/STREAM/OTHER)
.setResType(Type)
// 設(shè)置額外的參數(shù)(主要解決動態(tài)的拼在url中的參數(shù)难菌。eg: www.xxx.com/news/1, 最后的那個1為動態(tài))
.setExtraDynamicParam(String)
// 臨時的BaseUrl
.setBaseUrl(String)
// 鏈接超時時間
.setConnectOutTime(Long)
// 讀取時間
.setReadOuTime(Long)
// 寫入時間
.setWriteOutTime(Long)
// 需要加密的參數(shù)的key试溯, 可根據(jù)key去加密其中類型的參數(shù), 在初始化時使用到了郊酒,還記得嗎(上去看看)
.setEncryptionKey(Long)
// 設(shè)置MediaType
.setMediaType(String)
// 發(fā)送文件
.setPullFileParams()
// 接受文件
.setPushFileParams()
// 設(shè)置臨時頭部
.setHeads(String[])
// 綁定生命周期遇绞,防止內(nèi)存泄漏(忘了?上面有說)
.setTransformer(...)
// 數(shù)據(jù)回調(diào)(2章節(jié)中講到的一些回調(diào))
(1).start(CallBack);
// 獲得上游燎窘, 用戶自己處理結(jié)果
(2).getFlowable(Class);
// 同步請求
(3).synchronizationNet(Class)
5. 獲取上游并處理(已zip合并為例摹闽, 這里只是用了兩個, 其實RxJava提供了好多褐健, 當(dāng)然還有其他用法付鹿,詳情可以看RxJava的用法)
// zip
// 1. 得到wanAndroid的上游發(fā)射器
Flowable wanAndroidFlowable = getWanAndroidFlowable();
// 2. 得到百度的上游發(fā)射器
Flowable baiduFlowable = getBaiduFlowable();
// 3. 合并
//noinspection unchecked
Flowable.zip(wanAndroidFlowable, baiduFlowable, new BiFunction<WanAndroidResponse, String, ZipEntity>() {
@Override
public ZipEntity apply(WanAndroidResponse wanAndroidResponse, String s) throws Exception {
ZipEntity zipEntity = new ZipEntity();
List<WanAndroidEntity> data = wanAndroidResponse.getData();
zipEntity.setData(data);
zipEntity.setBaidu(s);
return zipEntity;
}
}).subscribe(new Subscriber<ZipEntity>() {
@Override
public void onSubscribe(Subscription subscription) {
subscription.request(Integer.MAX_VALUE);
}
@Override
public void onNext(ZipEntity o) {
List<WanAndroidEntity> data = o.getData();
// 這里進(jìn)行模擬, 如果 wanAndroid 數(shù)據(jù)是必須的數(shù)據(jù), 為空就是錯誤
if (data == null || data.isEmpty()) {
Toast.makeText(MainActivity.this, "數(shù)據(jù)為空了", Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(MainActivity.this, "成功:\n" + o.toString(), Toast.LENGTH_SHORT).show();
}
@Override
public void onError(Throwable throwable) {
if (throwable instanceof EmptyError) {
Toast.makeText(MainActivity.this, "數(shù)據(jù)為空了", Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(MainActivity.this, "數(shù)據(jù)錯誤:\n" + throwable.getMessage(), Toast.LENGTH_SHORT).show();
}
@Override
public void onComplete() {
Toast.makeText(MainActivity.this, "結(jié)束", Toast.LENGTH_SHORT).show();
}
});
private Flowable getWanAndroidFlowable() {
return AutoNet.getInstance().createNet()
.setDomainNameKey("wanandroid")
.setSuffixUrl("/wxarticle/chapters/json")
.doGet()
// 設(shè)置追蹤舵匾, 為了在body攔截中俊抵, 不讓其他邏輯進(jìn)行了攔截
.setFlag(666)
.getFlowable(WanAndroidResponse.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io());
}
private Flowable getBaiduFlowable() {
return AutoNet.getInstance().createNet()
// 設(shè)置追蹤, 為了在body攔截中坐梯, 不讓其他邏輯進(jìn)行了攔截
.setFlag(666)
.getFlowable(String.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io());
}
6. 注解方式
6.1 注解介紹
- AutoNetAnontation 網(wǎng)絡(luò)參數(shù)設(shè)置(value(除去域名)徽诲、flag、 writeTime吵血、readTime谎替、connectOutTime)
- AutoNetBaseUrlKeyAnontation BaseUrl的選擇標(biāo)識key(value)
- AutoNetDisposableBaseUrlAnontation 本次請求臨時使用的BaseUrl(value)
- AutoNetDisposableHeadAnnontation 本次請求臨時使用的頭部信息(value[])
- AutoNetEncryptionAnontation 加密參數(shù)設(shè)置(key, value)
- AutoNetMediaTypeAnontation 請求的MediaType(value)
- AutoNetPatternAnontation 請求方式(value(get/post/put/delete))
- AutoNetStrategyAnontation 網(wǎng)絡(luò)請求策略(value(net/local/local_net/net_local))
- AutoNetTypeAnontation 請求和返回的請求類型(reqType(json/form/stream), resType(json/form/stream))
6.2 代理類名規(guī)則
如果是回調(diào)是內(nèi)部 則代理類名為 外層類名 + 回調(diào)類名 + AutoProxy
如果回調(diào)就是一個類 則代理類名為 回調(diào)類名 + AutoProxy
6.3 注意
如果使用的是注解方式請求網(wǎng)絡(luò), 在寫完類后践瓷,請build -> rebuild project院喜。
6.4 例子
一、普通請求
@AutoNetPatternAnontation(AutoNetPatternAnontation.NetPattern.GET)
@AutoNetAnontation("/init.php")
@AutoNetBaseUrlKeyAnontation("jsonTestBaseUrl")
public class doGet implements IAutoNetDataBeforeCallBack<TestResponseEntity>, IAutoNetDataCallBack<List<Entity>> {
@Override
public boolean handlerBefore(TestResponseEntity o, FlowableEmitter emitter) {
List<Entity> entitys = o.getList();
if(entitys == null || entitys.isEmpty()){
emitter.onError(new EmptyError());
return true;
}
emitter.onNext(entitys);
return true;
}
@Override
public void onSuccess(List<Entity> entitys) {
}
@Override
public void onFailed(Throwable throwable) {
}
@Override
public void onEmpty() {
}
}
先build下晕翠, 然后再需要發(fā)送該網(wǎng)絡(luò)連接時:
MainActivitydoGetAutoProxy.startNet(MainActivity.this喷舀, bindUntilEvent(ActivityEvent.DESTROY));
注意:MainActivitydoGetAutoProxy這個類生成的規(guī)則前面已給出
二、 上傳文件
@AutoNetBaseUrlKeyAnontation("upFile")
@AutoNetTypeAnontation(reqType = AutoNetTypeAnontation.Type.STREAM)
@AutoNetPatternAnontation(AutoNetPatternAnontation.NetPattern.POST)
public class PushFile implements IAutoNetDataCallBack, IAutoNetFileCallBack {
@Override
public void onFailed(Throwable throwable) {
}
@Override
public void onEmpty() {
}
@Override
public void onSuccess(Object entity) {
}
@Override
public void onPregress(float progress) {
}
@Override
public void onComplete(File file) {
}
}
請求方式:
MainActivityPushFileAutoProxy.pushFile(MainActivity.this, "upload", path + File.separator + "a.png");
三淋肾、 下載文件
@AutoNetBaseUrlKeyAnontation("downFile")
@AutoNetTypeAnontation(resType = AutoNetTypeAnontation.Type.STREAM)
@AutoNetAnontation("/apk/downLoad/android_4.2.4.apk")
public class PullFile implements IAutoNetDataCallBack<File>, IAutoNetFileCallBack {
@Override
public void onFailed(Throwable throwable) {
}
@Override
public void onEmpty() {
}
@Override
public void onSuccess(File entity) {
}
@Override
public void onPregress(float progress) {
}
@Override
public void onComplete(File file) {
}
}
請求方式:
MainActivityPullFileAutoProxy.pullFile(MainActivity.this, path, "pppig.apk");
7. 簡單的例子
初始化
AutoNetConfig config = new AutoNetConfig.Builder()
.isOpenStetho(BuildConfig.DEBUG)
.setDefaultDomainName(ApiConstant.BASE_POST_URL)
.build();
AutoNet.getInstance().initAutoNet(this, config).setBodyCallback(new IAutoNetBodyCallBack() {
@Override
public boolean body(Object flag, String body) {
// 全局的硫麻, 所有的請求都會到這里
// 在這里可以根據(jù)自己的統(tǒng)一的字段去判斷code什么的是否成功了
// 如果不成功可以以異常出去, 最后會在onFailed回調(diào)
if (!TextUtils.isEmpty(body)) {
try {
BaseResponse baseResponse = new Gson().fromJson(body, BaseResponse.class);
if (!baseResponse.isSuccess()) {
throw new CustomError(baseResponse.getMessage());
return true;
}
} catch (Exception e) {
emitter.onError(e);
return true;
}
}
return false;
}
});
簡單使用
AutoNet.getInstance().createNet()
.setSuffixUrl("/test")
.setParam("a", "a")
.setParam("b", 1)
.doPost()
.start(new TestListCallback());
private class TestListCallback extends AbsAutoNetCallback<TestListResponse, List<TestEntity>> {
@Override
public boolean handlerBefore(TestListResponse response, FlowableEmitter emitter) {
// 這里可以在數(shù)據(jù)返回以前樊卓, 再次指定要返回的數(shù)據(jù)拿愧, 并根據(jù)自己的業(yè)務(wù)去判斷是否為空(注意這里是在分線程中)
List<TestEntity> entitys = response.getData();
if (entitys == null || entitys.isEmpty()) {
emitter.onError(new EmptyError());
return true;
}
//noinspection unchecked
emitter.onNext(entitys);
return true;
}
@Override
public void onSuccess(List<TestEntity> entitys) {
bindUserInfo(entitys);
mEmptyLayout.showContent();
refreshLayout.refreshComplete();
}
@Override
public void onFailed(Throwable throwable) {
HandlerError.handlerError(throwable);
mEmptyLayout.showContent();
refreshLayout.refreshComplete();
}
@Override
public void onEmpty() {
HandlerError.handlerEmpty();
mEmptyLayout.showContent();
refreshLayout.refreshComplete();
}
}
2.0.+ 修改點(該版本修改較大, 架構(gòu)等都有修改碌尔, 所以和之前的版本可能有個別用法不同骡显,如果切換最新版本需要主要一下幾點)
一蔫仙、 支持了同步請求,異步請求
- 增添了synchronizationNet(Class)方法。 Class 即后臺返回的數(shù)據(jù)結(jié)構(gòu)類型调衰。
- 修改了getFlowable(Class), 增加參數(shù)Class碴倾。Class 即后臺返回的數(shù)據(jù)結(jié)構(gòu)類型检碗。
二扇雕、 body回調(diào)
- 去除 FlowableEmitter 參數(shù), 在之前需要進(jìn)行特出處理的比如 emitter.onError(new Custom("...")) 改為 throw new Custom("...")