ps.代码仅用于演示,与实际代码出入
{
"ret": "0",
"msg": "成功",
"data": [
{
"shoe_id": "128",
"shoe_name": "阿迪达斯"
}
]
}
public interface ShoeApi{
/**
* 某品牌 跑鞋列表
*
* @param brand_id 品牌id
* @return
*/
@POST("brand-shoe-list")
Observable<List<Shoe>> brandShoeList(@Field("brand_id") int brand_id);
}
被代理的接口,接口规则参照: Retrofit2风格 + RxJavaCallAdapter 。
@POST(url)
,url表示请求路径,但不包含域名。@POST("brand-shoe-list")
实际上是请求 http://xxx.com/brand-shoe-list;@Field(name)int value
,name
指参数名,value
参数值。Observable<T>
,T
是json实例化后的对象
@Data(name)
, json数据中"data"
字段存放可实例化数据,但也可能是其他名称。这时,通过@Data(name)
可指定字段名,name
默认"data"
;@String(name)
, 由于技术原因,将_json中某字段实例化成String
,需要添加此注释。name
作用跟@Data(name)
一样,但@String(name)
默认"msg"
;@AllResponse
, 解释整个json数据。
@String("msg")
Observable<String> join();
可解释下面的"msg"
{
"ret":0,
"msg":"成功"
}
@Data("user")
Observable<User> loadUser(@Field("did")int uid);
可解释下面"user"
字段
{
"user":{...}
}
@AllReponse
Observable<User> loadUser(...);
{
"uid":1,
"name":"小白"
}
/**
* 跑鞋Retrofit
*/
public class ShoeRetrofit extends BaseRetrofit {
@Override
public <T> T createApi(Class<T> clazz) {
RepositoryProxy proxy = getProxyBuilder().baseurl("http://wear.api.thejoyrun.com/") // 正式服务器域名
.testurl("http://wear.api.test.thejoyrun.com/") // 测试服务器域名
.setTestServer(isTestApi())// 是否测试服务器,默认false
.gson(GsonHelper.getGson())
.build();
return proxy.create(clazz);
}
}
(自己YY出来的类,并不是square那个Retrofit ^_^)
Retrofit其实并没实则作用,RepositoryProxy
才是重点。RepositoryProxy
设置 正式/测试服务器 域名(一定要有"http://"前序)。GsonHelper.getGson()
是对Gson进行了配置,json字段值是""
,也可正常解析成int
。
注意,不要自己写构造函数,会对单元测试造成影响。
public interface ShoePresenter extends Presenter {
/**
* 获取品牌跑鞋列表
*/
void loadShoeList(int brand_id);
}
/**
* 跑鞋Presenter
*/
public class ShoePresenterImpl implements ShoePresenter {
ShoeApi shoeApi;// 跑鞋api类
ShoeView shoeView;// 跑鞋View
// 在构造函数创建的实例,也可以用dagger注入
public ShoePresenterImpl(ShoeView shoeView) {
this.shoeView = shoeView;
this.shoeApi = new ShoeRetrofit().create(ShoeApi.class);// 创建api代理
}
@Override
public void loadShoeList(int brand_id) {
// 底层代码默认api运行在io线程,不需要再写subscribeOn(Schedulers.io())
shoeApi.brandShoeList(brand_id)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new SimpleSubscriber<List<Shoe>>() {
@Override
public void onNext(List<Shoe> shoes) {
shoeView.onShoesLoaded(shoes);// 回调数据给View
}
});
}
}
相信你能看懂的!
public class ShoeApiTest extends ApiCase {
// @Api(uid = 4, sid = "", isTestApi = true, value = ShoeRetrofit.class, useLocalTime = false)
@MockApi
ShoeApi shoeApi;
@Test
public void testBrandShoeList() throws Exception {
mockRetrofit.addLocalPath("brand-shoe-list", "shoe/shoe_list.json");
List<Shoe> list = shoeApi.brandShoeList(11, 1, 10)
.toBlocking()
.first();
Shoe shoe = list.get(0);
verifyShoe(shoe);
}
private void verifyShoe(Shoe shoe) {
Assert.assertEquals(shoe.shoe_id, 128);
Assert.assertEquals(shoe.shoe_name, "阿迪达斯");
}
}
shoe_list.json
{
"ret": "0",
"msg": "成功",
"data": [
{
"shoe_id": "128",
"shoe_name": "阿迪达斯"
}
]
}
TestCase继承ApiCase,才可以使用@MockApi、@Api,还有其他屌屌的功能。
对Api接口注释,在TestCase.setUp()之前,会自动用MockRetrofit
代理api。与new MockRetrofit().create(ShoeApi.class)
等效。
可让Api接口请求真实网络。一个Api接口,不能同时使用@MockApi
和@Api
。
@Api参数:
uid
sid
登陆信息sidisTestApi
是否请求测试服务器,false则请求正式服务器 (默认true)value
代理Api接口的RetrofituserLocalTime
请求服务器时,会进行url签名,真机上是获取服务器lasttime
,if true,会再请求服务器获取lasttime
,if false,直接用本地时间(默认false)
模拟网络请求,返回mock数据。
addLocalPath(url,path)
, url需与api方法注释@POST(url)
中url一致, path指本地mock数据路径(放在src/test/assets/目录下)addSuccess(path)
、addFail(path)
,其实与addLocalPath(...)
一样,只是path指向默认的success.son
和fail.json
。
RxJava的Observable。
toBlocking()
,将Observable
转成BlockingObservable
,强制同步处理;first()
,返回第一个处理的数据