I am currently looking into implementing the Retrofit API (after using Volley) into my app and I have some questions that I cannot seem to find answers to anywhere else so I will ask here.
How do I go about downloading images using Retrofit API? I am asking this because Volley has the ImageLoader class and NetworkedImageView etc. and was wondering if Retrofit has something similar?
I read that using the RequestIntercepter, it can add a header to every request. How is this different from just adding a static (or dynamic) header (#Header) in the interface's abstract method
How does Retrofit deal with nested JSON objects? I read it uses GSON to convert the JSON into java objects but the POJO class must have the same field names.
Thank you for reading
For your first doubt:
Retrofit no have feature to manager image as Volley and UIL has. The same company that developer Retrofit too have a nice lib to manager images called Picasso.
For your second doubt:
Headers that need to be added to every request can be specified using
a RequestInterceptor. The following code creates a RequestInterceptor
that will add a User-Agent header to every request.
for instance:
I developed a client to Parse.com and to all request I need set my keys in the header: see here Android-Retrofit-Example
public class RestClient {
private static RestClient mRestClient = null;
private static RestAdapter restAdapter;
private static RequestInterceptor requestInterceptor;
public static RestClient getInstance(){
if(mRestClient == null ){
mRestClient = new RestClient();
setup();
}
return mRestClient;
}
private static void setup(){
requestInterceptor = new RequestInterceptor() {
#Override
public void intercept(RequestFacade request) {
request.addHeader("X-Parse-Application-Id", "");
request.addHeader("X-Parse-REST-API-Key", "");
}
};
restAdapter = new RestAdapter.Builder()
.setEndpoint(" https://api.parse.com/1/")
.setLogLevel(RestAdapter.LogLevel.FULL)
.setRequestInterceptor(requestInterceptor)
.build();
}
public RestAdapter getRestAdapter(){
return restAdapter;
}
}
The last :
JSON CONVERSION
Retrofit uses Gson by default to convert HTTP bodies to and from JSON.
If you want to specify behavior that is different from Gson's defaults
(e.g. naming policies, date formats, custom types), provide a new Gson
instance with your desired behavior when building a RestAdapter. Refer
to the Gson documentation for more details on customization.
To get this :
{
results: [3]
{
createdAt: "2015-03-07T20:43:44.107Z"
objectId: "osCJ8PI65r"
updatedAt: "2015-03-08T00:45:37.539Z"
username: "Test 2"
},
{
createdAt: "2015-03-07T21:42:38.591Z"
objectId: "tkIi6Ll1Os"
updatedAt: "2015-03-07T21:42:38.591Z"
username: "Test 2"
},
{
createdAt: "2015-03-08T01:13:21.188Z"
objectId: "Cz0HqiYpwl"
updatedAt: "2015-03-08T04:21:18.069Z"
username: "Test 3"
}
}
Pojo :
public class User {
private String objectId;
private String username;
private String createdAt;
private String updatedAt;
//gerate getters and setters
}
public class WrappeUser {
#SerializedName(value="results")
List<User> results;
public List<User> getResults() {
return results;
}
public void setResults(List<User> results) {
this.results = results;
}
}
Related
Our team decide to use Retrofit 2.0 and I'm doing some initial research on this library. As stated in the title, I want parse some nested JSON objects via Retrofit 2.0 in our Android app.
For example, here is a nested JSON object with the format:
{
"title": "Recent Uploads tagged android",
"link": "https://www.flickr.com/photos/tags/android/",
"description": "",
"modified": "2015-10-05T05:30:01Z",
"generator": "https://www.flickr.com/",
"items": [
{
"title": ...
"link": ...
"media": {"m":"This is the value I want to get:)"}
"description": ...
"published": ...
"author": ...
"author_id": ...
"tags": ...
},
{...},
...
]
}
I'm interested in the JSON objects inside items array. I notice there are some posts about parsing nested JSON objects via Retrofit 1.X, but the latest Retrofit 2.0 APIs has changed a lot, which is confusing when adapting them to the new APIs.
Two possible solutions come into my mind:
Write my own JSON converter factory which extends Converter.Factory.
Return the raw response in a String type and parse it by myself. But it's not easy to get the raw response from Retrofit 2.0 according to my initial research. Retrofit 2.0 seems to insist in converting the response to something before pass it to me and Retrofit doesn't provide its own StringConverter. (I might be wrong~)
Update: We can actually get the raw response by setting JSONElement as the pojo for the HTTP API interface and use GSONConverter provided by Retrofit as the converter.
Assuming your complete JSON looks like
{
"title": "Recent Uploads tagged android",
"link": "https://www.flickr.com/photos/tags/android/",
"description": "",
"modified": "2015-10-05T05:30:01Z",
"generator": "https://www.flickr.com/",
"items": [
{
"member1": "memeber value",
"member2": "member value"
},
{
"member1": "memeber value",
"member2": "member value"
}
]
}
So Pojo classes would be
public class MainPojo {
private String title;
private String description;
private String link;
private String generator;
private String modified;
private ArrayList<Items> items;
// Getters setters
}
public class Items {
private String member2;
private String member1;
// Getters setters
}
Note : This is similar solution for your JSON. Members of Items.java can be changed if JSON has other keys.
Update for Pojo as new JSON
public class Items {
private String tags;
private String author;
private String title;
private String description;
private String link;
private String author_id;
private String published;
private Media media;
// Getters and Setters
}
public class Media {
private String m;
// Getters and Setters
}
Following code will help to get nested json object and array
for example: json
{
"similar_product":[
{ .....
}
],
"options":{
"Blouse Length":[
{ "value_id":"696556",
}
first we need to create model class, model class items names are same in json item we can use #SerializedName("for exact json name")
public class Product {
public Options options;
public void setOptions(Options options) {
this.options = options;
}
public Options getOptions() {
return options;
}
// length...
public class Options
{
#SerializedName("Blouse Length")
private ArrayList<BlouseLength> blouseLengths;
public void setBlouseLengths(ArrayList<BlouseLength> blouseLengths) {
this.blouseLengths = blouseLengths;
}
public ArrayList<BlouseLength> getBlouseLengths() {
return blouseLengths;
}
}
public class BlouseLength {
String value_id;
public void setValue_id(String value_id) {
this.value_id = value_id;
}
public String getValue_id() {
return value_id;
}
}
}
create Interface for retrofit to get json item in url
// don't need to put values of id in retrofit
ex:: "/api-mobile_.php?method=getProductById&pid="
just pass url parameter in query it automatically fetch the url
for example:
public interface Retrofit_Api {
#FormUrlEncoded
#GET("/api-mobile_.php?method=getProductById")
Call<Product> responseproduct(#Query("pid") String pid);
}
In your Main class
String pid=editid.getText().toString();
final Retrofit adapter = new Retrofit.Builder()
.baseUrl(Product_url)
.addConverterFactory(GsonConverterFactory.create())
.build();
//Creating an object of our api interface
Retrofit_Api api = adapter.create(Retrofit_Api.class);
Call<Product> call = api.responseproduct(pid);
call.enqueue(new Callback<Product>() {
#Override
public void onResponse(Call<Product> call, Response<Product> response) {
ArrayList<Product.BlouseLength> p= new ArrayList(response.body().getOptions().getBlouseLengths());
Editadapter editadapter=new Editadapter(MainActivity.this,p);
recyclerView.setAdapter(editadapter);
}
#Override
public void onFailure(Call<Product> call, Throwable t) {
Log.d("Error", t.getMessage());
}
});
}
Use Gson easy parsing for your models https://github.com/google/gson
My Helper Methods :
public String toJson(Object object) {
return gson.toJson(object);
}
public <T> T fromJson(String json, Class<T> classOfT) {
return gson.fromJson(json, classOfT);
}
public <T> T fromJson(JsonElement jsonElement, Class<T> classOfT) {
return gson.fromJson(jsonElement, classOfT);
}
have you tried volley? ...i prefer it over retrofit now that is a google product.I have working example and if u dont mind i can show you.
http://www.androidhive.info/2014/09/android-json-parsing-using-volley/
I forgot add #SerializedName and #Expose annotations for inner Class objects and after add these annotations problem solved. Like this:
JSON:
{"Id": 1,}
and Class member:
#SerializedName("Id")
#Expose
private int id;
In my application I want POST some data, and this data get users and POST to server. For server requests I use Retrofit2.
For POST this data I should POST with json format, such as this :
{
"email": "example#example.com",
"username": "example",
"password": "123",
}
After POST data I should check with this results for submit data has Ok ro Not.
{
"status": 200,
"Message": "",
"data": true
}
I give Email, Username and Password with EditText from users, but how can I POST this data to server with Json format?
Please help me, I am amateur and I really need this help
Firstly, create a class for your request, for example, LoginRequest.java
public class LoginRequest {
private String email;
private String username;
private String password;
//getters and setters
}
Secondly, create a class for your response, LoginResponse.java
public class LoginResponse {
private Integer status;
private String Message;
private Boolean data;
//getters and setters
}
Finally, in your interface add this method:
public interface MiApiInterface {
#POST("yourResourceName") Call<LoginResponse> login(#Body LoginRequest request);
}
I hope It could help you, just ask me if you have more question.
have you realised that the return of the login method is a Call, it is for a async call, you could use it like this on your activity:
firstly, create a retrofit instance
Retrofit retrofit = ....
Secondly, create your interface instance like this:
MiApiInterface apiInterface = retrofit.create(MiApiInterface.class);
Finally, you could access the login method:
LoginRequest request = new LoginRequest();
request.set();
....
Call<LoginResponse> responseCall = apiInterface.login(request);
responseCall.enqueue(new Callback<LoginResponse>() {
public void onResponse(...){
LoginResponse loginResponse = response.body();
}
public void onFailure(...){
}
}
To Convert Objects to Json automatically, you should add a Converter Factory on your retrofit builder:
Gson gson = new GsonBuilder().create();
Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
...
dont forget import the Gson library on your gradle.
Here is a tutorial on Retrofit 2: http://www.vogella.com/tutorials/Retrofit/article.html
Alternatively, you can use Volley, it is a library specificaly designed to make http requests on Android. https://developer.android.com/training/volley/index.html
From git There was a such a suggestion
but I don't know how to use it,where to call ,any tip could be useful
retrofit lets to convert json,xml ,but I need to have as a object,converted data and string as well
#GET("whatever")
Call<Pair<User, String>> whatever();
Type firstType = //reflection
Converter<ResponseBody, Object> delegate = retrofit.nextResponseBodyConverter(firstType, annotations);
return new Converter<ResponseBody, Pair<Object, String>>() {
#Override public Pair<Object, String> convert(ResponseBody body) {
String string = body.string();
Object object = delegate.convert(ResponseBody.create(null, string));
return new Pair<>(object, string);
}
};
Please, checkout the Retrofit documentation first. It's useful.
You can also go through this tutorial. It's a little bit long, but it is good enough.
All in all you need four things:
POJO (Plain Old Java Object) a.k.a Student, Car, User etc.
REST client - check out the tutorial
Interface where to describe each part of the API - check out the tutorial
Wait for the callback from retrofit when you make a call to the API and do whatever you want with the info - check out the tutorial
If your #GET request is receiving something like that:
{
"user": {
"id": 1,
"name": "John"
},
"str": "Hello World"
}
Interface:
public interface MyInterface {
#GET("/api/user/1")
Call<ResponseBody> getMyObject();
}
Make the request:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://server.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
MyInterface service = retrofit.create(MyInterface.class);
service.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Response<ResponseBody> response, Retrofit retrofit) {
String raw = response.body().string();
MyObject object = new Gson().fromJson(raw, MyObject.class);
}
#Override
public void onFailure(Throwable t) {
}
});
Our team decide to use Retrofit 2.0 and I'm doing some initial research on this library. As stated in the title, I want parse some nested JSON objects via Retrofit 2.0 in our Android app.
For example, here is a nested JSON object with the format:
{
"title": "Recent Uploads tagged android",
"link": "https://www.flickr.com/photos/tags/android/",
"description": "",
"modified": "2015-10-05T05:30:01Z",
"generator": "https://www.flickr.com/",
"items": [
{
"title": ...
"link": ...
"media": {"m":"This is the value I want to get:)"}
"description": ...
"published": ...
"author": ...
"author_id": ...
"tags": ...
},
{...},
...
]
}
I'm interested in the JSON objects inside items array. I notice there are some posts about parsing nested JSON objects via Retrofit 1.X, but the latest Retrofit 2.0 APIs has changed a lot, which is confusing when adapting them to the new APIs.
Two possible solutions come into my mind:
Write my own JSON converter factory which extends Converter.Factory.
Return the raw response in a String type and parse it by myself. But it's not easy to get the raw response from Retrofit 2.0 according to my initial research. Retrofit 2.0 seems to insist in converting the response to something before pass it to me and Retrofit doesn't provide its own StringConverter. (I might be wrong~)
Update: We can actually get the raw response by setting JSONElement as the pojo for the HTTP API interface and use GSONConverter provided by Retrofit as the converter.
Assuming your complete JSON looks like
{
"title": "Recent Uploads tagged android",
"link": "https://www.flickr.com/photos/tags/android/",
"description": "",
"modified": "2015-10-05T05:30:01Z",
"generator": "https://www.flickr.com/",
"items": [
{
"member1": "memeber value",
"member2": "member value"
},
{
"member1": "memeber value",
"member2": "member value"
}
]
}
So Pojo classes would be
public class MainPojo {
private String title;
private String description;
private String link;
private String generator;
private String modified;
private ArrayList<Items> items;
// Getters setters
}
public class Items {
private String member2;
private String member1;
// Getters setters
}
Note : This is similar solution for your JSON. Members of Items.java can be changed if JSON has other keys.
Update for Pojo as new JSON
public class Items {
private String tags;
private String author;
private String title;
private String description;
private String link;
private String author_id;
private String published;
private Media media;
// Getters and Setters
}
public class Media {
private String m;
// Getters and Setters
}
Following code will help to get nested json object and array
for example: json
{
"similar_product":[
{ .....
}
],
"options":{
"Blouse Length":[
{ "value_id":"696556",
}
first we need to create model class, model class items names are same in json item we can use #SerializedName("for exact json name")
public class Product {
public Options options;
public void setOptions(Options options) {
this.options = options;
}
public Options getOptions() {
return options;
}
// length...
public class Options
{
#SerializedName("Blouse Length")
private ArrayList<BlouseLength> blouseLengths;
public void setBlouseLengths(ArrayList<BlouseLength> blouseLengths) {
this.blouseLengths = blouseLengths;
}
public ArrayList<BlouseLength> getBlouseLengths() {
return blouseLengths;
}
}
public class BlouseLength {
String value_id;
public void setValue_id(String value_id) {
this.value_id = value_id;
}
public String getValue_id() {
return value_id;
}
}
}
create Interface for retrofit to get json item in url
// don't need to put values of id in retrofit
ex:: "/api-mobile_.php?method=getProductById&pid="
just pass url parameter in query it automatically fetch the url
for example:
public interface Retrofit_Api {
#FormUrlEncoded
#GET("/api-mobile_.php?method=getProductById")
Call<Product> responseproduct(#Query("pid") String pid);
}
In your Main class
String pid=editid.getText().toString();
final Retrofit adapter = new Retrofit.Builder()
.baseUrl(Product_url)
.addConverterFactory(GsonConverterFactory.create())
.build();
//Creating an object of our api interface
Retrofit_Api api = adapter.create(Retrofit_Api.class);
Call<Product> call = api.responseproduct(pid);
call.enqueue(new Callback<Product>() {
#Override
public void onResponse(Call<Product> call, Response<Product> response) {
ArrayList<Product.BlouseLength> p= new ArrayList(response.body().getOptions().getBlouseLengths());
Editadapter editadapter=new Editadapter(MainActivity.this,p);
recyclerView.setAdapter(editadapter);
}
#Override
public void onFailure(Call<Product> call, Throwable t) {
Log.d("Error", t.getMessage());
}
});
}
Use Gson easy parsing for your models https://github.com/google/gson
My Helper Methods :
public String toJson(Object object) {
return gson.toJson(object);
}
public <T> T fromJson(String json, Class<T> classOfT) {
return gson.fromJson(json, classOfT);
}
public <T> T fromJson(JsonElement jsonElement, Class<T> classOfT) {
return gson.fromJson(jsonElement, classOfT);
}
have you tried volley? ...i prefer it over retrofit now that is a google product.I have working example and if u dont mind i can show you.
http://www.androidhive.info/2014/09/android-json-parsing-using-volley/
I forgot add #SerializedName and #Expose annotations for inner Class objects and after add these annotations problem solved. Like this:
JSON:
{"Id": 1,}
and Class member:
#SerializedName("Id")
#Expose
private int id;
I am writing my first code in Retrofit 1.9 version. I tried to follow several blog but not able to understand very basic problem. So far, I have created Model class using jsonschema2pojo, RestAdapter class.
Here is my model class:
#Generated("org.jsonschema2pojo")
public class GmailOauth {
#Expose
private String createdAt;
#Expose
private String objectId;
#Expose
private String sessionToken;
#Expose
private String username;
..... Getter and Setter methods...
I have created above model class using Jsonschema2pojo. So, my response JSON is very understandable.
Adapter class
public class RestApiAdapter {
public static final String BASE_URL = "http://testingserver.com:8081";
public RestAdapter providesRestAdapter(Gson gson) {
return new RestAdapter.Builder()
.setEndpoint(BASE_URL)
.build();
}
}
API class
interface GmailSignInAPI {
#POST("/signWithGmail")
void GmailOauthLogin(#Body GmailOauth user, Callback<GmailOauth> cb);
}
Now, I am confused how to write Retrofit client to pass following form-data post parameter in efficient way?
accessToken (String value)
userID (String value)
How about if I want to pass custom object in a post request and save the response of request in same object? Is this good way to do it?
I think for the api portion of Retrofit I would put
#FormUrlEncoded
#Post("/path/to/whatever")
void authenticateWithSomeCredentials(#Field("username") String userName, Callback<Object> reponse
Then I would call it like this:
public void authenticateWithSomeCredentials(username), new Callback<Object>() {
#Override
public void success(Object object, Response response) {
// Do something
}
#Override
public void failure(RetrofitError error) {
// Do something
}
}
To add the token to every call you could add an interceptor:
public class YourAuthInterceptor implements interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
request = chain.request().newBuilder()
.addHeader("token"), tokenVariable)
.build();
return chain.proceed(request);
}
}
this will add a "token" to every call you make with retrofit
so then when you build your api you build it like this
YourApi api = new RestAdapter.Builder()
.setEndpoint(url)
.setRequestInterceptor(new YourAuthInterceptor())
.build()
.create(YourApi.class);
I hope this makes sense as I am typing it rather quickly. If you have any questions please let me know.
You can do it like this:
#FormUrlEncoded
#POST("/postTosServer")
void postToServer(#Field("accessToken") String your_token, #Field("userID") String userid);