We have used Volley as networking library in lot of my articles. Today we are going to look at another awesome library Retrofit to make the http calls. Retrofit is denitely the better alternative to volley in terms of ease of use, performance, extensibility and other things. It is a type-safe REST client for Android built by Square. Using this tool android developer can make all network stuff much more easier. As an example, we are going to download some json and show it in RecyclerView as a list.
Here is the final app we are about to build.
Getting TMDB API Key / Sample JSON
For this tutorial we will use The TMDb API. In order to use this API it is necessary to obtain the API key. Here you can take a look how to obtain the API key. In short, you need to register and login in order to obtain the key.
After this it should looks like this
1. Creating New Project
1. Create a new project in Android Studio from File ⇒ New Project. When it prompts you to select the default activity, select Empty Activity and proceed.
2. Open build.gradle and add Retrofit, Gson dependencies.
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.3.0' // retrofit, gson compile 'com.google.code.gson:gson:2.6.2' compile 'com.squareup.retrofit2:retrofit:2.0.2' compile 'com.squareup.retrofit2:converter-gson:2.0.2' }
3. Since we are working with network operations we need to add INTERNET permissions in AndroidManifest.xml file
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="info.androidhive.retrofit"> <uses-permission android:name="android.permission.INTERNET"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".activity.MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
4. Create four sub packages named activity, adapter, rest and model in your main package. Move your MainActivity under activity package.
2. Creating Model Class
5. First, we need to know what type of JSON response we will be receiving. The following example uses The TMDb API as an example and show how to create Java objects that will be able to parse the latest movies. Based on the JSON response returned for this API call, let’s first define how a basic movie representation should look like:
Using this route (http://api.themoviedb.org/3/movie/top_rated?api_key=INSERT_YOUR_API_KEY) we can get the last 50 movies. Let’s insert it into browser and see. Using JsonViewer you can see JSON in more structured way. Copy the response from browser to this JsonViewer and this online tool show JSON like here:
6. Create a class named Movie.java under model package.
package info.androidhive.retrofit.model; import com.google.gson.annotations.SerializedName; import java.util.ArrayList; import java.util.List; public class Movie { @SerializedName("poster_path") private String posterPath; @SerializedName("adult") private boolean adult; @SerializedName("overview") private String overview; @SerializedName("release_date") private String releaseDate; @SerializedName("genre_ids") private List<Integer> genreIds = new ArrayList<Integer>(); @SerializedName("id") private Integer id; @SerializedName("original_title") private String originalTitle; @SerializedName("original_language") private String originalLanguage; @SerializedName("title") private String title; @SerializedName("backdrop_path") private String backdropPath; @SerializedName("popularity") private Double popularity; @SerializedName("vote_count") private Integer voteCount; @SerializedName("video") private Boolean video; @SerializedName("vote_average") private Double voteAverage; public Movie(String posterPath, boolean adult, String overview, String releaseDate, List<Integer> genreIds, Integer id, String originalTitle, String originalLanguage, String title, String backdropPath, Double popularity, Integer voteCount, Boolean video, Double voteAverage) { this.posterPath = posterPath; this.adult = adult; this.overview = overview; this.releaseDate = releaseDate; this.genreIds = genreIds; this.id = id; this.originalTitle = originalTitle; this.originalLanguage = originalLanguage; this.title = title; this.backdropPath = backdropPath; this.popularity = popularity; this.voteCount = voteCount; this.video = video; this.voteAverage = voteAverage; } public String getPosterPath() { return posterPath; } public void setPosterPath(String posterPath) { this.posterPath = posterPath; } public boolean isAdult() { return adult; } public void setAdult(boolean adult) { this.adult = adult; } public String getOverview() { return overview; } public void setOverview(String overview) { this.overview = overview; } public String getReleaseDate() { return releaseDate; } public void setReleaseDate(String releaseDate) { this.releaseDate = releaseDate; } public List<Integer> getGenreIds() { return genreIds; } public void setGenreIds(List<Integer> genreIds) { this.genreIds = genreIds; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getOriginalTitle() { return originalTitle; } public void setOriginalTitle(String originalTitle) { this.originalTitle = originalTitle; } public String getOriginalLanguage() { return originalLanguage; } public void setOriginalLanguage(String originalLanguage) { this.originalLanguage = originalLanguage; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getBackdropPath() { return backdropPath; } public void setBackdropPath(String backdropPath) { this.backdropPath = backdropPath; } public Double getPopularity() { return popularity; } public void setPopularity(Double popularity) { this.popularity = popularity; } public Integer getVoteCount() { return voteCount; } public void setVoteCount(Integer voteCount) { this.voteCount = voteCount; } public Boolean getVideo() { return video; } public void setVideo(Boolean video) { this.video = video; } public Double getVoteAverage() { return voteAverage; } public void setVoteAverage(Double voteAverage) { this.voteAverage = voteAverage; } }
7. Also we need to create MovieResponse.java class, since we have some extra fields like page number. This class contains all fetched movies and extra information. Create MovieResponse.java under model package.
package info.androidhive.retrofit.model; import com.google.gson.annotations.SerializedName; import java.util.List; public class MoviesResponse { @SerializedName("page") private int page; @SerializedName("results") private List<Movie> results; @SerializedName("total_results") private int totalResults; @SerializedName("total_pages") private int totalPages; public int getPage() { return page; } public void setPage(int page) { this.page = page; } public List<Movie> getResults() { return results; } public void setResults(List<Movie> results) { this.results = results; } public int getTotalResults() { return totalResults; } public void setTotalResults(int totalResults) { this.totalResults = totalResults; } public int getTotalPages() { return totalPages; } public void setTotalPages(int totalPages) { this.totalPages = totalPages; } }
3. Creating the Retrofit instance
8. To send network requests to an API, we need to use the Retrofit Builder class and specify the base URL for the service. So, create a class named ApiClient.java under rest package.
Here BASE_URL – it is basic URL of our API. We will use this URL for all requests later.
package info.androidhive.retrofit.rest; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; public class ApiClient { public static final String BASE_URL = "http://api.themoviedb.org/3/"; private static Retrofit retrofit = null; public static Retrofit getClient() { if (retrofit==null) { retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); } return retrofit; } }
4. Define the Endpoints
The endpoints are defined inside of an interface using special retrofit annotations to encode details about the parameters and request method. In addition, the return value is always a parameterized Call<T> object such as Call<MovieResponse>. For instance, the interface defines each endpoint in the following way.
9. Create ApiInterface.java under rest package.
package info.androidhive.retrofit.rest; import info.androidhive.retrofit.model.MoviesResponse; import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.Path; import retrofit2.http.Query; public interface ApiInterface { @GET("movie/top_rated") Call<MoviesResponse> getTopRatedMovies(@Query("api_key") String apiKey); @GET("movie/{id}") Call<MoviesResponse> getMovieDetails(@Path("id") int id, @Query("api_key") String apiKey); }
So, using this route the retrofit will generate the following URL:
http://api.themoviedb.org/3/movie/top_rated?api_key=12345678910111213
Each endpoint specifies an annotation of the HTTP method (GET, POST, etc.) and the parameters of this method can also have special annotations (@Query, @Path, @Body etc.)
Take a look to other annotations:
@Path – variable substitution for the API endpoint. For example movie id will be swapped for{id} in the URL endpoint.
@Query – specifies the query key name with the value of the annotated parameter.
@Body – payload for the POST call
@Header – specifies the header with the value of the annotated parameter
5. Making the First Request
10. Let’s make the first request from our MainActivity. If we want to consume the API asynchronously, we call the service as follows. Open the MainActivity.java and do the below changes.
Make sure that you replaced API_KEY with yours.
public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); // TODO - insert your themoviedb.org API KEY here private final static String API_KEY = ""; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (API_KEY.isEmpty()) { Toast.makeText(getApplicationContext(), "Please obtain your API KEY first from themoviedb.org", Toast.LENGTH_LONG).show(); return; } ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class); Call<MoviesResponse> call = apiService.getTopRatedMovies(API_KEY); call.enqueue(new Callback<MoviesResponse>() { @Override public void onResponse(Call<MoviesResponse>call, Response<MoviesResponse> response) { List<Movie> movies = response.body().getResults(); Log.d(TAG, "Number of movies received: " + movies.size()); } @Override public void onFailure(Call<MoviesResponse>call, Throwable t) { // Log error here since request failed Log.e(TAG, t.toString()); } }); } }
Retrofit will download and parse the API data on a background thread, and then return the results back to the UI thread via the onResponse or onFailure method.
Congratulations! We have created our first rest client. Let’s create some UI in order to see our results.
6. Displaying the Results in RecyclerView
11. Let’s create ListView for fetched results. We will use RecyclerView for it. First of all, add it to the gradle.gradle
dependencies { . . // recycler view compile 'com.android.support:recyclerview-v7:23.3.0' }
In order to show fetched items we need to create layout, which will show all data. We need 4 TextView and 1 ImageView for star image.
12. Open colors.xml and add the below color values.
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#3F51B5</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorAccent">#FF4081</color> <color name="orange">#FF3909</color> <color name="colorAccentDark">#00B482</color> <color name="colorBlack">#555555</color> <color name="colorWhite">#FFFFFF</color> <color name="colorGrey">#707070</color> <color name="colorGreyLight">#8A8A8A</color> </resources>
13. Create a layout named star.xml under res drawable with the below content.
<!-- drawable/star.xml --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportHeight="24" android:viewportWidth="24"> <path android:fillColor="#000" android:pathData="M12,17.27L18.18,21L16.54,13.97L22,9.24L14.81,8.62L12,2L9.19,8.62L2,9.24L7.45,13.97L5.82,21L12,17.27Z" /> </vector>
14. Create a layout named list_item_movie.java under res layout.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/movies_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:minHeight="72dp" android:orientation="horizontal" android:padding="16dp"> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical"> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="top" android:paddingRight="16dp" android:textStyle="bold" android:textColor="@color/colorBlack" android:textSize="16sp" /> <TextView android:id="@+id/subtitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingRight="16dp" android:textColor="@color/colorGreyLight" /> <TextView android:id="@+id/description" android:layout_width="wrap_content" android:layout_height="wrap_content" android:maxLines="3" android:paddingRight="16dp" android:textColor="@color/colorGreyLight" /> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="35dp" android:orientation="horizontal"> <ImageView android:id="@+id/rating_image" android:layout_width="15dp" android:layout_height="15dp" android:layout_centerInParent="true" android:scaleType="centerCrop" android:src="@drawable/star" android:tint="@color/colorAccent" /> <TextView android:id="@+id/rating" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="8dp" android:text="5.0" /> </LinearLayout> </LinearLayout>
15. Adapter is a common pattern which helps to bind view and data, so let’s implement adapter for this. Create a class named MoviesAdapter.java under adapter package.
package info.androidhive.retrofit.adapter; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; import java.util.List; import info.androidhive.retrofit.R; import info.androidhive.retrofit.model.Movie; public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MovieViewHolder> { private List<Movie> movies; private int rowLayout; private Context context; public static class MovieViewHolder extends RecyclerView.ViewHolder { LinearLayout moviesLayout; TextView movieTitle; TextView data; TextView movieDescription; TextView rating; public MovieViewHolder(View v) { super(v); moviesLayout = (LinearLayout) v.findViewById(R.id.movies_layout); movieTitle = (TextView) v.findViewById(R.id.title); data = (TextView) v.findViewById(R.id.subtitle); movieDescription = (TextView) v.findViewById(R.id.description); rating = (TextView) v.findViewById(R.id.rating); } } public MoviesAdapter(List<Movie> movies, int rowLayout, Context context) { this.movies = movies; this.rowLayout = rowLayout; this.context = context; } @Override public MoviesAdapter.MovieViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(rowLayout, parent, false); return new MovieViewHolder(view); } @Override public void onBindViewHolder(MovieViewHolder holder, final int position) { holder.movieTitle.setText(movies.get(position).getTitle()); holder.data.setText(movies.get(position).getReleaseDate()); holder.movieDescription.setText(movies.get(position).getOverview()); holder.rating.setText(movies.get(position).getVoteAverage().toString()); } @Override public int getItemCount() { return movies.size(); } }
16. Open MainActivity.java and modify the code as below.
package info.androidhive.retrofit.activity; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.widget.Toast; import java.util.List; import info.androidhive.retrofit.R; import info.androidhive.retrofit.adapter.MoviesAdapter; import info.androidhive.retrofit.model.Movie; import info.androidhive.retrofit.model.MoviesResponse; import info.androidhive.retrofit.rest.ApiClient; import info.androidhive.retrofit.rest.ApiInterface; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); // TODO - insert your themoviedb.org API KEY here private final static String API_KEY = ""; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (API_KEY.isEmpty()) { Toast.makeText(getApplicationContext(), "Please obtain your API KEY from themoviedb.org first!", Toast.LENGTH_LONG).show(); return; } final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.movies_recycler_view); recyclerView.setLayoutManager(new LinearLayoutManager(this)); ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class); Call<MoviesResponse> call = apiService.getTopRatedMovies(API_KEY); call.enqueue(new Callback<MoviesResponse>() { @Override public void onResponse(Call<MoviesResponse> call, Response<MoviesResponse> response) { int statusCode = response.code(); List<Movie> movies = response.body().getResults(); recyclerView.setAdapter(new MoviesAdapter(movies, R.layout.list_item_movie, getApplicationContext())); } @Override public void onFailure(Call<MoviesResponse> call, Throwable t) { // Log error here since request failed Log.e(TAG, t.toString()); } }); } }
Run the app and we get this nice list
To sum it up, Retrofit is one of the best tool for working with network requests. I have considered most common cases which can be helpful in your projects. Happy coding!
Hi there! I am Founder at androidhive and programming enthusiast. My skills includes Android, iOS, PHP, Ruby on Rails and lot more. If you have any idea that you would want me to develop? Let’s talk: ravi@androidhive.info
Thanks for the tutorial
This one is for Retrofit 2.0 ?
Yes, sure.In Retrofit 2.0, we will need json converter as an extra dependency.
Thanks for the tutorial
woocommerce & wordpress native android app tutorial Please
Awesome , will execute and Let you know !!
Hi is that getMovieDetails working now?
Can you able to get movieDetail json object?
Yes , it works , but you’ll have to make minor changes
@GET(“movie/{id}”)
Call getMovieDetails(@Path(“id”) int id, @Query(“api_key”) String apiKey);
to
@GET(“movie/{id}”)
Call getMovieDetails(@Path(“id”) int id, @Query(“api_key”) String apiKey);
and then use it accordingly !
hi rakhi can u teach me how to highlight filtered string in listview… i have done of filter but highlight is pending…. patilshashi43@gmail.com please mail me
woocommerce & wordpress native android app tutorial Please.
Hi Ravi, need to fix in heading 6. Displaying the Results in RecyclerView , for “gradle.gradle” to “build.gradle”.
Thnx. I’ll modify it.
Thanks Ravi, for your awesome tutorial .
Hi Ravi, I am using OKHTTP for my projects, Can you please give me an advice for library choice for http calls?
Which one is better.?
1. OKHTTP
2. Retrofit
3. Volly
I have a big list of Data with Images get from Azure. help me.
Pls go through this
http://stackoverflow.com/questions/16902716/comparison-of-android-networking-libraries-okhttp-retrofit-volley
Hi Ravi.. Im Sorry,I dont know how to ask for and where..I just need Help.
How to create code when the application has close without Click Button STOP
but music still running,and the icon app appears in bar mobile..
Please Help Me..
cecesyamsul@gmail.com
RetroFit of course For Restful Api
Volley vs Retrofithttp://i.imgur.com/tIdZkl3.png
Thanks
Thanks for the Tutorial. Can you please also add retrofit2 with rx and dagger 2?
I have json string
{
“type”: “s”,
“version”: “1.0”,
“data”: {
“name1”: { “id”:”5″, “title”:”abcxyz” },
“name2”: {“id”:”8″, “title”:”lalalal”},
“name3”: {“id”:”3″, “title”:”abc”},
“name4”: {“id”:”10″, “title”:”bloblal”},
“name5”: {“id”:”11″, “title”:”no”},
… and go to “name150”
(have 150 json Object in Object “data”)
}
In Model package, i don’t know how to create class
(create class with name1, name2, name3, … name150) i don’t think so. Help me.
I don’t develop json Respone. so i don’t know how to fix.
Thx!
I haven’t tried but read these
http://stackoverflow.com/questions/5796948/how-to-parse-dynamic-json-fields-with-gson
http://stackoverflow.com/questions/7304002/how-to-parse-a-dynamic-json-key-in-a-nested-json-result
use below link
http://www.jsonschema2pojo.org/
Hi bro ! I can recommend you to use lombok library which will produce all your getter, setter, and constructors at runtime. Also builder pattern is done with lombok. Your model classes will be so much clear 🙂
ooooooooh you really you are best programmer in the world thank you so much Mr.Ravi
but Finally I have a Big problem all android Developers dropped in it.
This Problem is Design Pattern for android (MVC Pattern) I am confusing about how can i use it. perfectly I see Some library handle this issue but i don’t know which one better and which one the best practices.
I hope to make a tutorial for best MVC pattern it’s so important for fast and accuracy and stable coding
This is one of Library handle this problem
https://github.com/kejunxia/AndroidMvc
but i want you advice and how can i use it for big projects with calling back-en and update view and handle all controllers with some advance patterns like observer pattern.
Thanks Mezooo for your suggestion. I strongly look into best solution for it.
Why app is crassing Caused by: java.lang.IllegalArgumentException: baseUrl must end in /:
anybody help me plz
What is info.androidhive.retrofit.R? It pops up in the main activity and the adapter but I dont see what it’s trying to import.
It’s your projects package name. In Android Studio, goto Build -> Clean Project. The .R file will be generated each time you change something in your project.
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.eliteappsbd.retrofitexm/com.eliteappsbd.retrofitexm.activity.MainActivity}: java.lang.IllegalArgumentException: baseUrl must end in /: https://api.themoviedb.org//3//movie//550?api_key=a2f888b27315e62e471b2d587048f32e//
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2455)
Caused by: java.lang.IllegalArgumentException: baseUrl must end in /: https://api.themoviedb.org//3//movie//550?api_key=a2f888b27315e62e471b2d587048f32e//
at retrofit2.Retrofit$Builder.baseUrl(Retrofit.java:496)
at retrofit2.Retrofit$Builder.baseUrl(Retrofit.java:439)
at com.eliteappsbd.retrofitexm.rest.ApiClient.getClient(ApiClient.java:16)
at com.eliteappsbd.retrofitexm.activity.MainActivity.onCreate(MainActivity.java:44)
Please help me
Caused by: java.lang.IllegalArgumentException: baseUrl must end in /: https://api.themoviedb.org/3/movie/550?api_key=a2f888b27315e62e471b2d587048f32e
at retrofit2.Retrofit$Builder.baseUrl(Retrofit.java:496)
at retrofit2.Retrofit$Builder.baseUrl(Retrofit.java:439)
at com.eliteappsbd.retrofitexm.rest.ApiClient.getClient(ApiClient.java:16)
at com.eliteappsbd.retrofitexm.activity.MainActivity.onCreate(MainActivity.java:44)
Any idea, how to get more and more movies on the list? It just stops after 20 results. How do i push the request to get more results?
Great tutorial . Can you also add for making multiple HTTP request using retrofit.
Hi Ravi, how to send POST request?
Im need to autorization in server. Server response JSON(user data)
{
“error”: false,
“message”: “suc”,
“token”: “2d60d05de0a39428c3d6a6cd33d230aa”,
“fio”: ” Arslanali”,
“phone”: “7”,
“myСhief”: “my”
}
Hi Ravi, I ‘m able to file download with Retrofit, but i have to update UI for download process, Retrofit is not OK for that now, How can I handle to Update with Retrofit?
I haven’t tried file upload yet. Pls check this
https://github.com/pratikbutani/RetrofitImageUpload
Thank you @Ravi Tamada:disqus for Sharing 🙂
final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.movies_recycler_view);
Where’s the id movies_recycler_view?
in activity_main.xml
You have to declare an recycler view inside activity_main.xml
Can we take response in String rather than in POJO class using Retrofit 2.0
Its Great
Great Tut, Can you do a tut on how to use this library to parse XML very little stuff online about parsing XML with retrofit.
I’m trying to do this in a fragment but I’m stuck at this line:
ApiInterface apiService =ApiClient.getClient().create(ApiInterface.class);
I haven’t been able to find any way around it, please help anyone? I get “unreachable statement”
Also I got stuck a long time on the ApiInterface because I was trying to create the POST without having the model first. As soon as you create the POST, GET you should make the Call sendSomething etc. to avoid the error.
Edit: So far it worked. I was putting the code into oncreateview and now changed it to onviewcreated
Thanks ravi but can we use both volley and retrofit at the same time ?– http://www.androidxu.com
Great tutorial Thanks, Can you create same retrofit 2 with post examples like image upload and etc
Hello Ravi, really great tutorial.
As @Chandrahasan I would also like to request you a tutorial on retrofit 2 with Post, Headers and multipart request also
Hi Ravi, Good work you are doing here. You deserve a gold medal!!
I would like to add to @rivu_chk:disqus’s and @Chandrahasan’s requests. Please add the following to part 2 of the tutorial.
1. CRUD operations.
2. Handling json error response from within the public void failure(){…} method and displaying it to the user.(not just logging the error). I have seen several tutorials which do so on the success method..
This requires that the api return a status code of 200 every time but containing the error json response. My api returns actual [400,404,422] responses. Please help with this as i have tried everything but to no avail.
3. Image handling using glide (in collaboration with retrofit)
Thanks in advance
Hi Nimzy
Thanks you for suggestions. I’ll try to update the article, but not very soon as I am working on other articles.
Hi Ravi great article! I was wondering for for getmovieDetails with movie/id which returns a different json , we wouldn’t be able to use it with MoviesResponse . So what change do we need to make inorder to parse and get data from the json which doesn’t have “results” , it is simply plain body . Please check http://api.themoviedb.org/3/movie/246655?api_key=API_KEY.
Thanks
Great tutorial Thanks, Can you create same retrofit 2 with post method example.
Hi Ravi, Awesome article. I was getting following 2 exception while requesting my api. 1.java.lang.ExceptionInInitializerError
2. java.lang.NoClassDefFoundError: okhttp3.internal.Util. I had lot of search but not able to get proper answer can you help me to resolve? I was used to with retrofit 1.9 but this 2.+ all versions I found this 2 exception.
I am too not sure about these errors. Even I need to search Did you able to run the downloaded project I have given?
Yes. I have downloaded it. It works fine. Even my application with retrofit 2 works fine but when I add google pay service dependency and run I get this two exceptions. Is it like that google play service have some problem with OKHTTP3 library?
Can you give me the exception?
07-09 11:10:59.769 7425-7425/com.example.plugshare E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.ExceptionInInitializerError
at com.example.plugshare.MainActivity.getOpenChargingStation(MainActivity.java:27)
at com.example.plugshare.MainActivity.onCreate(MainActivity.java:22)
at android.app.Activity.performCreate(Activity.java:5203)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2078)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2139)
at android.app.ActivityThread.access$700(ActivityThread.java:143)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1241)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4960)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ExceptionInInitializerError
at okhttp3.OkHttpClient$Builder.(OkHttpClient.java:359)
at com.example.plugshare.ServiceGenerator.(ServiceGenerator.java:35)
at com.example.plugshare.MainActivity.getOpenChargingStation(MainActivity.java:27)
at com.example.plugshare.MainActivity.onCreate(MainActivity.java:22)
at android.app.Activity.performCreate(Activity.java:5203)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2078)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2139)
at android.app.ActivityThread.access$700(ActivityThread.java:143)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1241)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4960)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NoClassDefFoundError: okhttp3.internal.Util
at okhttp3.OkHttpClient.(OkHttpClient.java:61)
at okhttp3.OkHttpClient$Builder.(OkHttpClient.java:359)
at com.example.plugshare.ServiceGenerator.(ServiceGenerator.java:35)
at com.example.plugshare.MainActivity.getOpenChargingStation(MainActivity.java:27)
at com.example.plugshare.MainActivity.onCreate(MainActivity.java:22)
at android.app.Activity.performCreate(Activity.java:5203)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2078)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2139)
at android.app.ActivityThread.access$700(ActivityThread.java:143)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1241)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4960)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
at dalvik.system.NativeStart.main(Native Method)
http://stackoverflow.com/questions/38278868/retrofit-2-with-google-play-service-exception?noredirect=1#comment63976708_38278868
http://stackoverflow.com/questions/38278868/retrofit-2-with-google-play-service-exception
FATAL EXCEPTION: main
java.lang.ExceptionInInitializerError
at com.example.plugshare.MainActivity.getOpenChargingStation(MainActivity.java:27)
at com.example.plugshare.MainActivity.onCreate(MainActivity.java:22)
at android.app.Activity.performCreate(Activity.java:5203)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2078)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2139)
at android.app.ActivityThread.access$700(ActivityThread.java:143)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1241)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4960)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ExceptionInInitializerError
at okhttp3.OkHttpClient$Builder.(OkHttpClient.java:359)
at com.example.plugshare.ServiceGenerator.(ServiceGenerator.java:35)
at com.example.plugshare.MainActivity.getOpenChargingStation(MainActivity.java:27)
at com.example.plugshare.MainActivity.onCreate(MainActivity.java:22)
at android.app.Activity.performCreate(Activity.java:5203)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2078)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2139)
at android.app.ActivityThread.access$700(ActivityThread.java:143)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1241)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4960)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NoClassDefFoundError: okhttp3.internal.Util
at okhttp3.OkHttpClient.(OkHttpClient.java:61)
at okhttp3.OkHttpClient$Builder.(OkHttpClient.java:359)
at com.example.plugshare.ServiceGenerator.(ServiceGenerator.java:35)
at com.example.plugshare.MainActivity.getOpenChargingStation(MainActivity.java:27)
at com.example.plugshare.MainActivity.onCreate(MainActivity.java:22)
at android.app.Activity.performCreate(Activity.java:5203)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2078)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2139)
at android.app.ActivityThread.access$700(ActivityThread.java:143)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1241)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4960)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
at dalvik.system.NativeStart.main(Native Method)
Adding this two jars worked for me…
compile files(‘libs/okhttp-3.4.1.jar’)
compile files(‘libs/okio-1.10.0.jar’)
Thanks Ravi for the tutorial.
Awesome tutorial can you post more retrofit series videos..
There are really important maybe some retrofit with php app with writing and reading and authentication ..
This will provide complete set of information ..
Looking forward to next tutorials
Thank you ravi
thanks ravi for great tutorial, i followed all your code in this article. I’m trying to make recyclerview which show the data from restaurant. The retrofit has succeeded get data from server, in log the data return in number of all registered restaurant. But i got an error, like “no adapter attached skipping layout in activity”. Can you help me ? thanks
how to create detail view from list view..
Hello, another great tutorial from you :).
What exactly do I need to make POST call not GET.
Also if I’m using realm can I convert directly from Json response to realm model ?
Hi Ravi,
Nice tut…Can you share the tut for getting XML response from http calls using retrofit..
retrofit.RetrofitError: Unable to resolve host
: No address associated with hostname
Check your URl and it should have procol too i.e http://
I think you missed to add “movies_recycler_view” in your activity_main.xml
Thanks for the great tutorial, there is a small update
In ApiInterface
Instead of
@GET(“movie/{id}”)
Call getMovieDetails(@Path(“id”) int id, @Query(“api_key”) String apiKey);
It will be
@GET(“movie/{id}”)
Call getMovieDetails(@Path(“id”) int id, @Query(“api_key”) String apiKey);
Exactly I was wondering , why I wasn’t getting a response even after passing id and api key properly!
Hi Dhiraj,
Can you please post your onCreate method from the MainActivity.java. Please.
Thanks,
Nithin
I got this error: Could not identify launch activity: Default Activity not found
Error while Launching activity
Why when I change the MainActivity to the subpackage activity the manifest doesn’t recognize it?
After analyzing your demo, I realized my packages weren’t at the main folder, they were outside so the manifest and layout coulnd’t find the MainActivity. I corrected them and everything went ok! Nice practice.
Hello sir, how to handle errors in retrofit?
Where is the Recycler view xml? U missed I thnink..
how to get all values of a row element on another page
pass with intent
how to retry retrofit request in 2.x ?
can we use REST api with JDBC(Mysql) database!!!!!!!!!!!
YES
can you give me example to make seach filter on bar using retrofit recyclerview?
Thank you Ravi… That’s Awesome. 🙂
Nice Ravi … it gave awesome concept