Diante de um projeto com um problema até então não visto. Eu tive que fumar a documentação e, neste artigo, mostrarei como usar o RxJava e o Retrofit 2 - você pode resolver o problema de criar um cliente Odata para um aplicativo Android.Muito obrigado Jake Wharton por criar essas ferramentas confortáveis.Bem-vindo ao mundo da magia
Temos um aplicativo que, de acordo com o protocolo Odata, deve extrair dados do servidor, exibi-los em listas que devem ser carregadas à medida que rola e enviar os dados criados pelo usuário para o servidor. Uma tarefa trivial, mas não estava aqui, o que funciona sem problemas em Java - também não quer funcionar com o Android.E as bibliotecas e a documentação no Odata são apenas do Apache - Olingo e Microsoft em C #.Neste artigo , não considerarei o protocolo Odata , a Microsoft possui uma documentação muito boa e deixarei os links no final do artigo.Aqui está uma breve definição com o Wiki Open_Data_ProtocolProtocolo de dados abertos (OData)Open Data Protocol (OData) — - . , HTTP-, XML JSON.
4.0, OData — , OASIS.
E aqui começa a parte mais interessante: Odata é um tipo de SQL na API REST e, para dados dinâmicos , é exatamente isso.Mas temos uma linguagem fortemente tipada e sem conhecimento do modelo - o processamento e o armazenamento de dados criam uma tarefa bastante difícil.A solução não pode ser padrão e descrita repetidamente na rede.Vou dizer ainda mais, exceto por esses links para a documentação na rede - tudo está ruim sobre o assunto.Agora vamos fazer a mágica:Criar um serviço para trabalhar com a rede.Usaremos Retrofit 2 e relacionados Quadrados produtos.inclua dependências no arquivo 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 Todas essas dependências são a biblioteca de rede mais poderosa em Java. Não vejo o objetivo dedescrever como trabalhar com o Retrofit 2 , aqui está um bom manual: usamos o Retrofit 2 em um aplicativo Android .Crie a classe 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 Crie a API:public interface ApiService {
@GET("odata/product")
Observable<List<ProductsDto>> getProducts();
}
listing 3 E criamos algum tipo de controlador para receber solicitações: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 Portanto, o modelo de dados Poduct é armazenado no servidor, que possui alguns parâmetros e atributos. Todos os dados vão no formato JSON e, para o trabalho, precisamos de uma classe POJO.Eu recomendo no HttpLoggingInterceptor para configurar o nível de detalhe de interceptação - Level.BODY.Fazemos uma solicitação de listagem 4 para maximizar a estrutura de dados e a resposta será aproximadamente neste formato:
{
"@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"
}
]
}
Listagem 5E já com base nesses dados, é possível solicitar uma manipulação adicional de dados.Ou seja, este é um objeto completo com algum tipo de comportamento e atributos, para obter essas informações ao criar uma solicitação, é necessário adicionar condições com base nas quais receberemos nosso DataSource sem inventar uma bicicleta nova e sem apertar muletas.O clímax e o deleite dos filhotes com o conforto do instrumento
E aqui o momento é verdadeiro, o poder, a força e a simplicidade da biblioteca Retrofit 2 . Agora você pode obter propriedades usando o documento de serviço 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);
Listagem 6Aqui está a heroica biblioteca Silushka, Retrofit 2 . O URL dinâmico assume toda essa massa de parâmetros com os quais você pode reproduzir o código enquanto tiver imaginação suficiente.Vai parecer algo assim: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 Sumário
Foi uma experiência útil, que me apressei em compartilhar, no devido tempo, este artigo realmente removeria muitos problemas e perguntas.No artigo, não entrei em detalhes desnecessários no Retrofit 2 e OData e indiquei links para a documentação se houvesse necessidade de aprofundar.Não posso fornecer a versão completa do código, pelo qual peço desculpas, o produto é comercial.E, como prometido, vincula:→ Documentação da Microsoft: Open Data Protocol→ Documentação OData 4.0 Java Library→ Crie aplicativos da Internet totalmente funcionais usando o Open Data Protocol