anuchandy / reactor-android-sample

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Reactor Android Sample

A sample Android application that make use of following modules:

Application min SDK version is 26.

Sample demonstrates using Reactor to make asynchronous HTTP call and display the result in UI.

GitHub expose an API to retrieve contributors of any public repo anonymously. The sample uses this API to retrieve top 5 contributors of atmost 3 repos.

alt text

Using reactor-okhttp

reactor-okhttp includes a Reactor based light weight HttpClient that uses Square OkHttp underneath.

Configuring OkHttp HttpClient for GitHub API

The HttpClientBuilder is used to configure and build an reactor-okhttp HttpClient.

// import reactor.okhttp.http.client.HttpClient;

final String accessToken = null; // github token, null for anonymous access.
final String githubApiHost = "api.github.com";

HttpClient httpClient = new HttpClientBuilder()
    .addInterceptor((httpRequest, nextInterceptor) -> {
        if (accessToken != null) {
            httpRequest.setHeader("Authorization", "token " + accessToken);
        }
        httpRequest.setHeader("Accept", "application/vnd.github.v3+json");
        httpRequest.setHeader("Host", githubApiHost);
        return nextInterceptor.intercept(httpRequest);
    })
    .build();

addInterceptor is used for registering an interceptor that sets necessary HTTP headers needed for calling GitHub API, this interceptor gets called for all http calls via HttpClient.

Calling GitHub API for list contributor

An Http call can be made using HttpClient's send method.

// import reactor.okhttp.http.client.HttpMethod;
// import reactor.okhttp.http.client.HttpRequest;
// import reactor.okhttp.http.client.HttpResponse;
// import com.google.gson.Gson;
// import com.google.gson.reflect.TypeToken;

final String githubOrganization = "reactor";
final String githubRepo = "reactor-core";
final String contributorsEndpoint = "https://api.github.com/repos/" 
    + githubOrganization + "/" 
    + githubRepo 
    + "/contributors";
    
HttpRequest request = new HttpRequest(HttpMethod.GET, toUrl(contributorsEndpoint)));
Mono<List<GitHub.Contributor>> contributorsMono = httpClient.send(request)
    .flatMap((Function<HttpResponse, Mono<String>>) httpResponse -> {
        if (httpResponse.getStatusCode() >= 400) {
            return httpResponse.getBodyAsString()
                .flatMap(content -> toErrorMono(httpResponse.getStatusCode(), content))
                .switchIfEmpty(Mono.defer(() -> toErrorMono(httpResponse.getStatusCode(), null)));
        } else {
            return httpResponse.getBodyAsString();
        }
    })
    .map(content -> deserializeContributors(content));

private static Mono<String> toErrorMono(int statusCode, String errorContent) {
    return Mono.<String>error(toThrowable(httpResponse.getStatusCode(), errorContent);
}

private static Throwable toThrowable(int statusCode, String errorContent) {
    if (errorContent != null) {
        return new Throwable("StatusCode:" + httpResponse.getStatusCode() + " Content: " + errorContent);
    } else {
        return new Throwable("StatusCode:" + httpResponse.getStatusCode());
    }
}

private static List<GitHub.Contributor> deserializeContributors(String content) {
    return (new Gson())
        .fromJson(content, new TypeToken<ArrayList<Contributor>>(){}.getType())
}

A subscription to contributorsMono initate the call to GitHub list contributors endpoint.

contributorsMono.subscribe(contributors -> {
    // process contributors
}, throwable -> {
    // log error
});

Using reactor-android

reactor-android includes a Reactor Scheduler implementation backed by Android main thread (UI thread). This scheduler is used to run Reactor subscription callbacks on Android main thread, this enables callbacks to access applications UI elements.

// import reactor.android.schedulers.AndroidSchedulers;
final android.view.View view = .. // The main view
final int resultTextViewId = .. // The resource id of TextView to display result
Disposable disposable = contributorsMono
    .subscribeOn(Schedulers.elastic())
    .publishOn(AndroidSchedulers.mainThread())
    .doOnNext(contributors -> {
        String contributorsStr = String.join("\n", 
            contributors.stream()
                .map(c -> c.getLogin())
                .collect(Collectors.toList()));
                
        TextView resultTextView = view.findViewById(resultTextViewId);
        resultTextView.setText(contributorsStr);
    })
    .doOnError(throwable -> {
        TextView resultTextView = view.findViewById(resultTextViewId);
        resultTextView.setText(throwable.getMessage());
    });

The operator publishOn is used here to set Reactor Android scheduler as the scheduler to run call backs.

About


Languages

Language:Java 100.0%