Retrofit 2.1 with RxAndroid

Retrofit is very known library to handle the network operation in Android. It is very powerful library to work with network related API call. It used OkHttp request in networking operation.

Earlier we used Async Task was having some drawback that retrofit has covered all. Here are the some drawback points in async Task.

1. Handling multiple request.
2. Cacheing data
3. Error handling

These all taking cared in Retrofit. But if talk about RxAndroid (Reactive Android) which works on based on Observable and Subscription. It makes our life very easy and make Retrofit very powerful if we used together. Rx Team and Retrofit team are doing a great job together.  Rx Java is ocean to work with Java that will not enough one day to understand. But day by day It attracting the Android developers that works very pathetic way with Android. Thats why It will be going used many and more places in the upcoming feature.

Thanks to both team to makes our life easy and networking operation makes more easy and stable to used this to make awesome apps.

Here is uploaded video that gives to understand to retrofit api call in android. Please check once to view before source code.

Lets create an android project to implement this.

build.gradle app level

    
     compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'io.reactivex:rxandroid:1.2.0'
    compile 'io.reactivex:rxjava:1.1.8'
    compile "com.jakewharton:butterknife:8.1.0"
    apt 'com.jakewharton:butterknife-compiler:8.0.1'
    compile 'org.greenrobot:eventbus:3.0.0'
    compile "com.android.support:recyclerview-v7:24.2.0"
    compile "com.android.support:cardview-v7:24.2.0"

APIService.java

    
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.sunil.rxjavaretrofitandroid.Friends;

import java.security.cert.CertificateException;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
import rx.Observable;

/**
 * Created by sunil on 12/25/16.
 */

public interface APIService {

    static final String BASE_URL = "https://demo4532688.mockable.io/";

    @GET("getmyfriends")
    Observable getMyFriends();

    class Creator {

        private static OkHttpClient okHttpClient1 = getUnsafeOkHttpClient();

        public static APIService newApiClient() {

            Gson gson = new GsonBuilder()
                    .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
                    .create();
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .client(okHttpClient1)
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .build();
            return retrofit.create(APIService.class);
        }

        private static OkHttpClient getUnsafeOkHttpClient() {
            try {
                // Create a trust manager that does not validate certificate chains
                final TrustManager[] trustAllCerts = new TrustManager[]{
                        new X509TrustManager() {
                            @Override
                            public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                            }

                            @Override
                            public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                            }

                            @Override
                            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                                return new java.security.cert.X509Certificate[]{};
                            }
                        }
                };

                // Install the all-trusting trust manager
                final SSLContext sslContext = SSLContext.getInstance("SSL");
                sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
                // Create an ssl socket factory with our all-trusting manager
                final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
                OkHttpClient.Builder builder = new OkHttpClient.Builder();
//                builder.addInterceptor(logging);

                builder.sslSocketFactory(sslSocketFactory);
                builder.hostnameVerifier(new HostnameVerifier() {
                    @Override
                    public boolean verify(String hostname, SSLSession session) {
                        return true;
                    }
                });

                OkHttpClient okHttpClient = builder.
                        connectTimeout(60, TimeUnit.SECONDS)
                        .readTimeout(60, TimeUnit.SECONDS)
                        .writeTimeout(60, TimeUnit.SECONDS)
                        .addInterceptor(new MyOkHttpInterceptor()).build();
                return okHttpClient;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}

MyOkHttpInterceptor.java

    
import android.util.Log;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.Buffer;

/**
 * Created by sunil on 12/25/16.
 */

public class MyOkHttpInterceptor implements Interceptor {
    private final String TAG = MyOkHttpInterceptor.class.getSimpleName();
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        String body = "NA";
        if(chain.request().body()!=null){
            body =  bodyToString(chain.request().body());
        }

        String myString = request.url() + " ->" + request.headers().toString()+"\n Params  --->"+body+"\n";

        Log.d(TAG, myString);
        return chain.proceed(request);
    }

    private  String bodyToString(final RequestBody request){
        try {
            final RequestBody copy = request;
            final Buffer buffer = new Buffer();
            copy.writeTo(buffer);
            return buffer.readUtf8();
        }
        catch (final IOException e) {
            return "did not work";
        }
    }

}

APIManager.java

    
import android.content.Context;
import com.sunil.rxjavaretrofitandroid.Friends;
import com.sunil.rxjavaretrofitandroid.event.FriendsEvent;
import org.greenrobot.eventbus.EventBus;
import java.io.IOException;
import retrofit2.adapter.rxjava.HttpException;
import rx.Observable;
import rx.Observer;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**
 * Created by sunil on 12/25/16.
 */

public class APIManager {

    private APIService mAPIService;

    public APIManager(Context context) {
        mAPIService = getAPIServiceEndPoint();

    }

    public APIService getAPIServiceEndPoint() {
        if (mAPIService == null) {
            mAPIService = APIService.Creator.newApiClient();
        }
        return mAPIService;
    }


    public void getFriends() {

        Observable friendResponseObservable = mAPIService.getMyFriends()
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread());

        friendResponseObservable.subscribe(new Observer() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {
                //handle error
                if (e instanceof HttpException) {
                    // We had non-2XX http error
                }
                if (e instanceof IOException) {
                    // A network or conversion error happened
                }

                // We don't know what happened. We need to simply convert to an unknown error
            }

            @Override
            public void onNext(Friends response) {
                //handle response
                EventBus.getDefault().post(new FriendsEvent(response));
            }
        });


    }

}

MainActivity.java

    
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.MenuItem;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.sunil.rxjavaretrofitandroid.adapter.FriendsAdapter;
import com.sunil.rxjavaretrofitandroid.api.APIManager;
import com.sunil.rxjavaretrofitandroid.event.FriendsEvent;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;

import butterknife.BindView;
import butterknife.ButterKnife;
import rx.Subscription;

public class MainActivity extends AppCompatActivity {

    @BindView(R.id.recyclerView1)
    RecyclerView mRecyclerView;
    @BindView(R.id.progressbar)
    ProgressBar progressbar;

    private APIManager mAPIManager;
    private Subscription mSubscription;

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

        setActionBarWithBackButton();

        progressbar.setVisibility(View.GONE);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mAPIManager = new APIManager(this);

        loadFriends();
    }

    protected void setActionBarWithBackButton() {
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeAsUpIndicator(getResources().getDrawable(R.drawable.navigate_back));
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this);
        }

    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mSubscription != null)
            mSubscription.unsubscribe();
        EventBus.getDefault().unregister(this);
    }

    public void loadFriends() {
        // use loader
        progressbar.setVisibility(View.VISIBLE);
        mAPIManager.getFriends();
    }

    @Subscribe
    public void OnEvent(FriendsEvent response) {
        // cancel loader
        progressbar.setVisibility(View.GONE);
        if (response.getFriends() != null) {
            if (response.getFriends().getUser().size() < 1) {
                Toast.makeText(this, "No Data available", Toast.LENGTH_LONG).show();
            } else {
                showFriends(response.getFriends());
            }
        }
    }

    public void showFriends(Friends friends) {
        FriendsAdapter adapter = new FriendsAdapter(friends.getUser());
        mRecyclerView.setAdapter(adapter);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                break;
        }
        return true;
    }
}


activity_main.xml

    
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.sunil.rxjavaretrofitandroid.MainActivity">


    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </android.support.v7.widget.RecyclerView>

    <ProgressBar
        android:id="@+id/progressbar"
        android:layout_centerInParent="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

FriendsAdapter.java

    
    public class FriendsAdapter  extends RecyclerView.Adapter{

    private List mListFriends;

    public FriendsAdapter(List friendsList){
        mListFriends = friendsList;
    }

    @Override
    public FriendsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_friends, parent, false);
        return new FriendsViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(FriendsViewHolder holder, int position) {
        Friends.User friends = mListFriends.get(position);
        holder.nameTextView.setText(friends.getName());
        holder.emailTextView.setText(friends.getEmail());
    }

    @Override
    public int getItemCount() {
        return mListFriends.size();
    }

    class FriendsViewHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.name)
        TextView nameTextView;
        @BindView(R.id.email)
        TextView emailTextView;

        public FriendsViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }
}

Thanks for reading this post. I hope it will help you. Please give your valuable comment below.

1 comment:

  1. it will really helpful if you could explain what the code does and why you use this code... thanks for sharing

    ReplyDelete

Debug Database in Android

In my last tutorial, we have learned how we can use persistence database in android. We also understood which database wrapper we can use...

Contact Me

Name

Email *

Message *