All Projects → matthiasbruns → rxandroid2-retrofit2

matthiasbruns / rxandroid2-retrofit2

Licence: other
Small tutorial to get started with RxAndroid 2 and Retrofit 2

Programming Languages

java
68154 projects - #9 most used programming language

Projects that are alternatives of or similar to rxandroid2-retrofit2

Kotlin Android Scaffolding
An android project structure using kotlin and most common libraries.
Stars: ✭ 53 (-3.64%)
Mutual labels:  android-development, android-application, rxjava2, retrofit2
BakingApp
Udacity Android Developer Nanodegree, project 2.
Stars: ✭ 54 (-1.82%)
Mutual labels:  rxjava2, retrofit2, retrofit2-rxjava, rxandroid2
Weather-Guru-MVP
Sample Material-design Android weather application build with MVP architectural approach using Dagger2, RxJava2, Retrofit2, Event-Bus, GreenDao, Butterknife, Lottie etc.
Stars: ✭ 15 (-72.73%)
Mutual labels:  android-development, rxandroid, rxjava2, retrofit2
Marvel
Marvel Characters Android Application Assigned by smava GmbH
Stars: ✭ 227 (+312.73%)
Mutual labels:  android-application, rxandroid, retrofit2
Open Source Android Weather App
☔️ Open source android weather app. See "Issues" tab for current tasks queue. Tasks suitable for beginners are labeled with green "beginner friendly" tags.
Stars: ✭ 81 (+47.27%)
Mutual labels:  android-application, rxjava2, retrofit2
Armscomponent
📦 A complete android componentization solution, powered by MVPArms (MVPArms 官方快速组件化方案).
Stars: ✭ 1,664 (+2925.45%)
Mutual labels:  android-application, rxjava2, retrofit2
Droid Feed
Aggregated Android news, articles, podcasts and conferences about Android Development
Stars: ✭ 174 (+216.36%)
Mutual labels:  android-development, android-application, retrofit2
ReactiveBus
🚍 Reactive Event Bus for JVM (1.7+) and Android apps built with RxJava 2
Stars: ✭ 17 (-69.09%)
Mutual labels:  rxandroid, rxjava2, rxandroid2
Fineract-CN-mobile
DEPRECATED project - Check the Apache fineract-cn-mobile project instead
Stars: ✭ 17 (-69.09%)
Mutual labels:  rxandroid, retrofit2, retrofit2-rxjava
InstantAppStarter
Starter Project Structure for Android Instant app. https://blog.mindorks.com/android-mvp-architecture-with-instant-app-support-11ba48241a82
Stars: ✭ 44 (-20%)
Mutual labels:  android-development, rxjava2, retrofit2
Android
Step by step guide for various components in android
Stars: ✭ 32 (-41.82%)
Mutual labels:  android-development, rxjava2, retrofit2
PopMovies
Aplicativo em Android para organização dos seus filmes favoritos.
Stars: ✭ 41 (-25.45%)
Mutual labels:  rxandroid, rxjava2, retrofit2
Seeweather
⛅ [@deprecated]RxJava+RxBus+Retrofit+Glide+Material Design Weather App
Stars: ✭ 3,481 (+6229.09%)
Mutual labels:  android-application, rxjava2, retrofit2
Stepik Android
Android Application for Taking Open Courses on the Stepik Platform
Stars: ✭ 165 (+200%)
Mutual labels:  android-application, rxjava2, retrofit2
Prefser
Wrapper for Android SharedPreferences with object serialization and RxJava Observables
Stars: ✭ 228 (+314.55%)
Mutual labels:  rxandroid, rxjava2, rxandroid2
Reactivenetwork
Android library listening network connection state and Internet connectivity with RxJava Observables
Stars: ✭ 2,484 (+4416.36%)
Mutual labels:  rxandroid, rxjava2, rxandroid2
Reactivebeacons
Android library scanning BLE beacons nearby with RxJava
Stars: ✭ 171 (+210.91%)
Mutual labels:  rxandroid, rxjava2, rxandroid2
Reactivewifi
Android library listening available WiFi Access Points and related information with RxJava Observables
Stars: ✭ 186 (+238.18%)
Mutual labels:  rxandroid, rxjava2, rxandroid2
Android-Starter-Kit
This is up-to-date android studio project for native android application, that is using modern tools and libraries.
Stars: ✭ 16 (-70.91%)
Mutual labels:  rxandroid, rxjava2, retrofit2
iMoney
iMoney 金融项目
Stars: ✭ 55 (+0%)
Mutual labels:  rxjava2, retrofit2, rxandroid2

RxAndroid 2 & Retrofit 2

This short guide explains how you setup and use Retrofit 2 with RxAndroid 2. The example code I use can be found here: https://github.com/matthiasbruns/rxandroid2-retrofit2

Project Setup

6682f70d70da9951e38bb61458faa630d4e742cf

We need two dependencies for this project. Add the lines below to your build.gradle in your app project under dependencies.

For RxAndroid:

compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.1.0'

and for Retrofit 2:

compile 'com.squareup.retrofit2:retrofit:2.3.0'

And add the adapter for retrofit2 to work with RxJava 2.

compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'

OPTIONAL

If you want to add support for GSON or another body parser, you can also add the following dependencies.

compile 'com.google.code.gson:gson:2.7'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'

Demo Webservice

For this guide we will use an open webservice called GeoNames. You can find its documentation here http://www.geonames.org/export/JSON-webservices.html

We will implement a simple example with the cities webservice.

Cities and Placenames

Webservice Type : REST
Url : api.geonames.org/citiesJSON?
Parameters :
north,south,east,west : coordinates of bounding box
callback : name of javascript function (optional parameter)
lang : language of placenames and wikipedia urls (default = en)
maxRows : maximal number of rows returned (default = 10)

Result : returns a list of cities and placenames in the bounding box, ordered by relevancy (capital/population). Placenames close together are filterered out and only the larger name is included in the resulting list.

An example call looks like this: http://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo

Retrofit Service Implementation

The trimmed JSON output of the query above looks like this

{
  "geonames": [
    {
      "lng": -99.12766456604,
      "geonameId": 3530597,
      "countrycode": "MX",
      "name": "Mexiko-Stadt",
      "fclName": "city, village,...",
      "toponymName": "Mexico City",
      "fcodeName": "capital of a political entity",
      "wikipedia": "en.wikipedia.org/wiki/Mexico_City",
      "lat": 19.428472427036,
      "fcl": "P",
      "population": 12294193,
      "fcode": "PPLC"
    },
    {
      "lng": 116.397228240967,
      "geonameId": 1816670,
      "countrycode": "CN",
      "name": "Peking",
      "fclName": "city, village,...",
      "toponymName": "Beijing",
      "fcodeName": "capital of a political entity",
      "wikipedia": "en.wikipedia.org/wiki/Beijing",
      "lat": 39.9074977414405,
      "fcl": "P",
      "population": 11716620,
      "fcode": "PPLC"
    }
  ]
}

To use GSON we need to define a network model class, which looks like this response of the api.

The "Response" object contains a list named "geonames".

// com.matthiasbruns.rxretrofit.network.CityResponse

public class CityResponse {

    public List<Geoname> geonames;
}

The list contains of "Geoname" models.

// com.matthiasbruns.rxretrofit.network.Geoname

public class Geoname {

    public double lat;
    public double lng;
    public long geonameId;
    public String countrycode;
    public String name;
    public String fclName;
    public String toponymName;
    public String fcodeName;
    public String wikipedia;
    public String fcl;
    public long population;
    public String fcode;
}

We have to add "username=demo" as a query parameter after every request. There is a way to do this automatically - with an OkHttp Interceptor.

9c42ed917d0d34b2e3f188e91d58d5083c2183d5

// com.matthiasbruns.rxretrofit.network.RetrofitHelper

/**
     * This custom client will append the "username=demo" query after every request.
     */
    private OkHttpClient createOkHttpClient() {
        final OkHttpClient.Builder httpClient =
                new OkHttpClient.Builder();
        httpClient.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                final Request original = chain.request();
                final HttpUrl originalHttpUrl = original.url();

                final HttpUrl url = originalHttpUrl.newBuilder()
                        .addQueryParameter("username", "demo")
                        .build();

                // Request customization: add request headers
                final Request.Builder requestBuilder = original.newBuilder()
                        .url(url);

                final Request request = requestBuilder.build();
                return chain.proceed(request);
            }
        });

        return httpClient.build();
    }

    private Retrofit createRetrofit() {
        return new Retrofit.Builder()
                .baseUrl("http://api.geonames.org/")
                .client(createOkHttpClient()) // <- add this
                .build();
    }

To enable GSON in retrofit, we also need to add a ConverterFactory to Retrofit.

// com.matthiasbruns.rxretrofit.network.RetrofitHelper

    private Retrofit createRetrofit() {
        return new Retrofit.Builder()
                .baseUrl("http://api.geonames.org/")
                .addConverterFactory(GsonConverterFactory.create()) // <- add this
                .client(createOkHttpClient())
                .build();
    }

The next step is the service itself. Retrofit does not need a real implementation of the service. All you have to do is to provide an interface which can consume the real api endpoint. For our use case the service may look like this:

// com.matthiasbruns.rxretrofit.network.CityService

@GET("citiesJSON")
Single<CityResponse> queryGeonames(@Query("north") double north, @Query("south") double south,
        @Query("east") double east, @Query("west") double west, @Query("lang") String lang);

As you can see, the method has all query parameters except the "username" parameter from the example query. Since the api listens to a GET request, we have to annotate this method with @GET("citiesJSON"). "citiesJSON" is the relative path to the root url of the api. All query parameters will be added to the whole request url. The return type Single is a RxJava typed CityResponse object. Single means, that if you subscribe to this method, it will only emit an item once or call onError. If you want to know more about RxJava 2 you should read this guide: https://github.com/balamaci/rxjava-walkthrough

The next step it the actual creation of the service.

// com.matthiasbruns.rxretrofit.networkRetrofitHelper

public CityService getCityService() {
    final Retrofit retrofit = createRetrofit();
    return retrofit.create(CityService.class);
}

Before we can finally work on Android code, we have to enable RxJava in Retrofit. 2408d9142d1d83be691485527316f187ec7cacdc

// com.matthiasbruns.rxretrofit.network.RetrofitHelper

private Retrofit createRetrofit() {
    return new Retrofit.Builder()
            .baseUrl("http://api.geonames.org/")
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // <- add this
            .client(createOkHttpClient())
            .build();
}

Using The Service

be9b654cbb2cb006dc114d1fb7bf9177345785ff

To use the service, you have to add the INTERNET permission first to the AndroidManifest

<uses-permission android:name="android.permission.INTERNET" />

In the MainActivity, we will add/replace the following code.

// com.matthiasbruns.rxretrofit.MainActivity

    /**
     * We will query geonames with this service
     */
    @NonNull
    private CityService mCityService;

    /**
     * Collects all subscriptions to unsubscribe later
     */
    @NonNull
    private CompositeDisposable mCompositeDisposable = new CompositeDisposable();

    private TextView mOutputTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mOutputTextView = (TextView) findViewById(R.id.output);

        // Initialize the city endpoint
        mCityService = new RetrofitHelper().getCityService();

        // Trigger our request and display afterwards
        requestGeonames();
    }

    @Override
    protected void onDestroy() {
        // DO NOT CALL .dispose()
        mCompositeDisposable.clear();
        super.onDestroy();
    }

    private void displayGeonames(@NonNull final List<Geoname> geonames) {
        // Cheap way to display a list of Strings - I was too lazy to implement a RecyclerView
        final StringBuilder output = new StringBuilder();
        for (final Geoname geoname : geonames) {
            output.append(geoname.name).append("\n");
        }

        mOutputTextView.setText(output.toString());
    }

    private void requestGeonames() {
        mCompositeDisposable.add(mCityService.queryGeonames(44.1, -9.9, -22.4, 55.2, "de")
                .subscribeOn(Schedulers.io()) // "work" on io thread
                .observeOn(AndroidSchedulers.mainThread()) // "listen" on UIThread
                .map(new Function<CityResponse, List<Geoname>>() {
                    @Override
                    public List<Geoname> apply(
                            @io.reactivex.annotations.NonNull final CityResponse cityResponse)
                            throws Exception {
                        // we want to have the geonames and not the wrapper object
                        return cityResponse.geonames;
                    }
                })
                .subscribe(new Consumer<List<Geoname>>() {
                    @Override
                    public void accept(
                            @io.reactivex.annotations.NonNull final List<Geoname> geonames)
                            throws Exception {
                        displayGeonames(geonames);
                    }
                })
        );
    }

The method requestGeonames calls the service endpoint we've created before. The result is being transformed into the geoname list. In the subscribe call, we send the geonames to the display logic, which simply loops through the list and displays the names of the Geoname object in a TextView.

Conclusion

I've shown you how you can easily combine the power of RxJava with Retrofit. We used a randomly picked JSON API (it was my first Google result) and created a Retrofit endpoint for the names API. Retrofit has opt-in support for RxJava2, which we used as the return type of our endpoint.

In the activity we subscribe to this created endpoint and display the received information in a simple way. I hope I could help you with this little guide to get you Retrofit2-RxJava2 setup working.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].