面对一个迄今尚未发现的问题的项目。我不得不抽烟文档,在本文中,我将告诉您如何使用RxJava和Retrofit 2-您可以解决为Android应用程序创建Odata客户端的问题。非常感谢Jake Wharton创建了如此舒适的工具。欢迎来到魔术世界
我们有一个应用程序,根据Odata协议,该应用程序必须从服务器提取数据,将其显示在应滚动显示的列表中,然后将用户创建的数据发送到服务器。一项微不足道的任务,但不是在这里,在Java中可以正常工作的问题-也不想在android上工作。而就在图书馆和文献的OData是只能从阿帕奇- Olingo和微软在C#。在本文中,我不会考虑Odata协议,Microsoft具有非常好的文档,并且在文章结尾处将保留链接。这是Wiki Open_Data_Protocol的简要定义开放数据协议(OData)Open Data Protocol (OData) — - . , HTTP-, XML JSON.
4.0, OData — , OASIS.
从最有趣的部分开始,Odata是REST API中的一种SQL,这就是动态生成数据的含义。但是我们有一种强类型的语言,并且不了解模型-数据处理和存储创建起来相当困难。解决方案不能是标准的,不能在网络上重复描述。除了这些指向网络文档的链接之外,我还要说的更多-该主题上的所有内容都是不好的。现在,让我们来做魔术:创建用于网络工作的服务,我们将使用Retrofit 2和相关的Square产品。将依赖项添加到build.gradle文件
implementation 'com.squareup.retrofit2:retrofit:2.7.1'
implementation 'com.squareup.retrofit2:converter-gson:2.7.1'
implementation 'com.squareup.okhttp3:logging-interceptor:4.3.1'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.7.1'
implementation 'com.squareup.okhttp3:okhttp:4.3.1'
listing 1 所有这些依赖项是Java中功能最强大的网络库。我看不到描述如何使用Retrofit 2的意义,这是一本很好的手册:我们在Android应用程序中使用Retrofit 2。创建NetworkService类:public class NetworkService {
private static final String TAG = "NetworkService";
private static final NetworkService
mInstance = new NetworkService();
private String mToken;
private Retrofit mRetrofit;
public static NetworkService getInstance() {
return mInstance;
}
private NetworkService() {
RxJava2CallAdapterFactory rxAdapter =
RxJava2CallAdapterFactory
.createWithScheduler(Schedulers.io());
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder okHttpClient =
new OkHttpClient.Builder()
.addInterceptor(interceptor)
.addInterceptor(chain -> {
Request newRequest =
chain.request().newBuilder()
.addHeader("Accept",
"application/json,text/plain,*/*")
.addHeader("Content-Type",
"application/json;odata.metadata=minimal")
.addHeader("Authorization", mToken)
.build();
return chain.proceed(newRequest);
});
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.create();
mRetrofit = new Retrofit.Builder()
.baseUrl(Const.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(rxAdapter)
.client(okHttpClient.build())
.build();
}
public ApiService getNetworkClient(){
return mRetrofit.create(ApiService.class);
}
}
listing 2 创建API:public interface ApiService {
@GET("odata/product")
Observable<List<ProductsDto>> getProducts();
}
listing 3 我们创建了某种控制器来拉取请求:public class ProductsController {
private ApiService mApiService;
private List<ProductsDto> listProducts;
private Gson gson;
public ProductsController() {
mApiService = App.getNetworkService().getNetworkClient();
listProducts = new ArrayList<>();
gson = new Gson();
}
public void productsBtnClick() {
mApiService.getProducts()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new DisposableObserver<List<ProductsDto>>() {
@Override
public void onNext(List<ProductsDto> products) {
listProducts.addAll(listProducts);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
listing 4 因此,Poduct数据模型存储在服务器上,该模型具有一些参数和属性。所有数据均采用JSON格式,并且在工作中我们需要一个POJO类。我建议在HttpLoggingInterceptor中配置拦截详细信息的级别-Level.BODY。我们提出清单4的请求,以最大化数据结构,并且答案将大致采用以下格式:
{
"@odata.context":"https://example.xxx/api/odata/$metadata","value":[
{
"name":"product","kind":"EntitySet","url":"product"
},{
"name":"blogs","kind":"EntitySet","url":"blogs"
},{
"name":"posts","kind":"EntitySet","url":"posts"
},{
"name":"comments","kind":"EntitySet","url":"comments"
},{
"name":"rates","kind":"EntitySet","url":"rates"
}
]
}
清单5并且已经基于该数据可以请求进一步的数据处理。也就是说,这是一个具有某种行为和属性的成熟对象,为了在创建请求时获取此信息,有必要添加条件,在此基础上我们将在不发明新自行车且无需拧紧拐杖的情况下接收我们的数据源。仪器舒适度高潮和幼犬愉悦
在这里,他的时刻是对的,Retrofit 2库的强大,强大和简单。现在,您可以使用Odata服务文档获取属性:
@GET("odata/product?$filter=Id eq 111&$expand=dateReading($orderby=Date desc")
Observable<List<ProductsDto>> getProducts();
// properties blogs
@GET("odata/blogs?$orderby=Date desc")
Observable<List<BlogsDto>> getBlogs();
//
@GET("odata/product?$filter=((Id eq 19) and (Name eq 'Available')) and ((Status eq 'OPEN') or ((Status eq 'CLOSED') and (Date ge 2020-02-13T06:39:48Z)))&$orderby=Status asc,Date desc&$top=10&$expand=AuthorId,CategoryId($expand=weight)&$count=true")
Observable<List<ProductsDto>> getProducts();
// ,
// .
// :
@GET
Observable<List<ProductsDto>> getProducts(@Url String url);
清单6这是Silushka英雄图书馆Retrofit 2。只要您有足够的想象力,Dynamic Url就会接受所有这些参数,您可以在代码中使用这些参数。它看起来像这样:private void buttonGetProduct() {
String one = "odata/product?$filter=Id eq ";
String id = "777";
String tree = "&$expand=dateReading($orderby=Date desc)";
String url = one + id + tree;
mApiService.getProduct(url)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new DisposableObserver<List<ProductDto>>() {
@Override
public void onNext(List<ProductDto> products) {
mProductsDto.addAll(countersDtos);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
listing 7 摘要
这是一种有用的经验,我希望与大家分享,在适当的时候,本文确实可以消除很多问题。在本文中,我没有涉及Retrofit 2和OData的不必要细节,并指出了是否有必要进行更深入研究的文档链接。抱歉,我无法提供完整版本的代码,因为该产品是商业产品。并且,如所保证的,链接:→ Microsoft文档:开放数据协议→ 文档OData 4.0 Java库→ 使用开放数据协议创建功能齐全的Internet应用程序