Iterate through Retrofit response - android

I'm using Retrofit for my Android app, calling it like this:
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(BASE_URL)
.build();
ApiEndpointInterface apiService = restAdapter.create(ApiEndpointInterface.class);
apiService.getFeed(9, new Callback<Post>() {
#Override
public void success(Post post, Response response) {
// loop
}
#Override
public void failure(RetrofitError retrofitError) {
retrofitError.printStackTrace();
}
});
The JSON is formatted like this:
{
"success":true,
"data":[
{
"id":"1",
"user_id":"2",
"message":"Hello, world!"
},
{
"id":"2",
"user_id":"1",
"message":"Another hello!"
}
]
}
How can I iterate through each item and, for example, print its message to console? Each item belongs to the Post model:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Post {
public String id;
public String userId;
public String message;
public String getMessage() {
return message;
}
}

Your Main model class look like this.
public class Post {
private String success;
private List<data> data;
public List<data> getData() {
return data;
}
}
Here is your data class.You need to create another class to retrieve json arary(For you it is data.)
public class data {
public String id;
public String userId;
public String message;
public String getMessage() {
return message;
}
}
apiService.getFeed(9, new Callback<Post>() {
#Override
public void success(Post post, Response response) {
post.getData().getPositoin(YourPosition).getMessage(); //or you can use for loop
}
#Override
public void failure(RetrofitError retrofitError) {
retrofitError.printStackTrace();
}
});

Related

How can I print out the results of this json file? (Android Retrofit2)

I want to show Json result in textview using retrofit2, but I can't get the desired result.
json
{
"rows" : [ {
"playerId" : "f8a49812eb9c3e5c8e738c3664e0ebd1",
"nickname" : "Yuichuan",
"grade" : 89
} ]
}
Model.class
public class Model {
public String playerId;
public String nickname;
public int grade;
public String getPlayerId() {
return playerId;
}
public void setPlayerId(String playerId) {
this.playerId = playerId;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
}
PlayerModel.class
public class PlayerModel {
public List<Model> rows;
}
**RetrofitFactory.class**
public class RetrofitFactory {
private static String BASE_URL="https://api.neople.co.kr/";
public static RetrofitService create(){
Retrofit retrofit=new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonC`enter code here`onverterFactory.create()).build();
return retrofit.create(RetrofitService.class);
}
}
RetrofitService.interface
public interface RetrofitService {
#GET("cy/players/")
Call<PlayerModel> getlist(#Query("nickname") String nickname,
#Query("apikey") String apikey);
}
MainActivityt
public class MainActivity extends AppCompatActivity {
private static final String API_KEY = "8yTuVMwy2DirHl2sWaZ3C8IJLslOfTpQ";
private static final String TAG ="Main" ;
TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView=findViewById(R.id.test);
RetrofitService networkService=RetrofitFactory.create();
networkService.getlist("Yuichuan",API_KEY)
.enqueue(new Callback<PlayerModel>() {
#Override
public void onResponse(Call<PlayerModel> call, Response<PlayerModel> response) {
if(!response.isSuccessful()){
textView.setText(response.code());
return;
}
Log.d(TAG, "onResponse: ConfigurationListener::"+call.request().url());
}
#Override
public void onFailure(Call<PlayerModel> call, Throwable t) {
textView.setText(t.getMessage());
}
});
}
}
I want to print out these json files, but it doesn't work as I want, so I want you to give me some help or advice.It seems like a simple problem, but it is very difficult for me because I am not used to json.
The textView.setText(response.code()); give you a code of response. To get your data model you need a body of response response.body()

Trying to get post from JsonPlaceHolder by retrofit, but response isn't showing methods

I'm new in retrofit, I'm trying to get single post from jsonplaceholder website, the problem is that I can't find getTitle, getBody, getId, and getUserId in onresponse method in callback. I typed (response.body.) , but getter methods doesn't appear.
MainActivity
public class MainActivity extends AppCompatActivity {
TextView tvText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvText=findViewById(R.id.tvText);
Retrofit retrofit= new Retrofit.Builder()
.baseUrl("https://jsonplaceholder.typicode.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiInterface apiInterface= retrofit.create(ApiInterface.class);
Call<POST> call= apiInterface.getPost();
call.enqueue(new Callback<POST>() {
#Override
public void onResponse(Call<POST> call, Response<POST> response) {
response.body().
}
#Override
public void onFailure(Call<POST> call, Throwable t) {
Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
Interface
public interface ApiInterface {
#GET("posts/1")
Call<POST> getPost();
}
Post class for json keys
public class Post {
private int id;
private int userId;
private String title;
private String body;
public int getId() {
return id;
}
public int getUserId() {
return userId;
}
public String getTitle() {
return title;
}
public String getBody() {
return body;
}
}
Xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res /android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="#+id/tvText"
android:layout_width="324dp"
android:layout_height="92dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
.....................
you need to do small change, the Call type should be Post not POST, as your model class name is Post.
working code
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_admin);
Retrofit retrofit= new Retrofit.Builder()
.baseUrl("https://jsonplaceholder.typicode.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiInterface apiInterface= retrofit.create(ApiInterface.class);
Call<Post> call= apiInterface.getPost();
call.enqueue(new Callback<Post>() {
#Override
public void onResponse(Call<Post> call, Response<Post> response) {
Log.i("response_title",response.body().getTitle()+"");
Log.i("response_userId",response.body().getUserId()+"");
Log.i("response_id",response.body().getId()+"");
Log.i("response_body",response.body().getBody()+"");
}
#Override
public void onFailure(Call<Post> call, Throwable t) {
}
});
}
public interface ApiInterface {
#GET("Posts/1")
Call<Post> getPost();
}
public class Post {
private int id;
private int userId;
private String title;
private String body;
public int getId() {
return id;
}
public int getUserId() {
return userId;
}
public String getTitle() {
return title;
}
public String getBody() {
return body;
}
}
}

Multiple progress bar in multiple view while api call

I am trying to make generic implementation for adding and showing progress bar in fragment / activity when there are multiple calls.
Anyone have any better solution rather than taking two references of progress bar and toggling its visibility? The implementation should be generic which can be applied to any views.
Add this interface in your Project....
public interface RetrofitCallback {
<T> void getSuccessCallBack(Response<T> response, int position);
void getErrorCallBack(String message, int position);
}
add these methods in your Utility or RetrofitUtility.
public static <T> void callRetrofit(final Context context, final Fragment fragment, Call<T> call, final int position, final RetrofitCallback callback) {
final ProgressDialog pDialog = CommonMethod.showProgressDialog(context, context.getResources().getString(R.string.loading));// progress for whole application
call.enqueue(new Callback<T>() {
#Override
public void onResponse(Call<T> call, Response<T> response) {
pDialog.dismiss();
if (response.isSuccessful()) {
ResultBody result = (ResultBody) response.body();
if (result.isSuccess())
callback.getSuccessCallBack(response, position);
else
callback.getErrorCallBack(result.getMessage(), position);
} else
Toast.makeText(context, response.message(), Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<T> call, Throwable t) {
pDialog.dismiss();
if (CommonMethod.checkconnection(context)) { // checking internet connection
Toast.makeText(context, "Server_error", Toast.LENGTH_SHORT).show();
} else {
CommonMethod.showconnectiondialog(context, fragment);
}
}
});
}
public static Retrofit getClient() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl("XXXXXXXXXXXXX")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
All Retrofit API
public interface RetrofitApi {
#POST("allData")
Call<UserData> getAllData();
}
Implement RetrofitCallback in your Activity and Fragment
Call Api like this
Call<UserData> call = ApiClient.getClient().create(RetrofitApi.class).getAllData();
ApiClient.callRetrofit(context, this, call, 0, this);
and you will get data from RetrofitCallback override methods below
#Override
public <T> void getSuccessCallBack(Response<T> response, int position) {
UserData userData = ((UserData) response.body());
// do your operation over here
}
#Override
public void getErrorCallBack(String message, int position) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
}
Here is all models file....
ResultBody.class
public class ResultBody {
private String message;
private boolean success;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
}
UserData.class
public class UserData extends ResultBody {
private User userData;
public User getUserData() {
return userData;
}
public void setUserData(User user) {
this.userData = user;
}
}
Let me know if you stuck anywhere.....
Relative Posts or Questions
Android:dynamically pass model class to retrofit callback

Retrofit not getting data from api

I have some api that contains JSON with partner names.
I've set up interface and pojo model. I'll post below my code.
Here is my POJO model Partner:
public class Partner {
#SerializedName("name")
#Expose
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Now here is my interface:
public interface APIService {
#GET("Partner")
Call<List<Partner>> getPartners();
}
And here is my APIHelper:
public class APIHelper {
public static final String PARTNERS_URL = "https://part-of-url.herokuapp.com/partners.json/";
public static APIService apiService;
public static APIService getApiService() {
if (apiService == null) {
Retrofit retrofit = new Retrofit.Builder().baseUrl(PARTNERS_URL)
.addConverterFactory(GsonConverterFactory.create()).build();
apiService = retrofit.create(APIService.class);
}
return apiService;
}
}
And this is Fragment which contains Button where onClick method needs to get data from web.
public class DownloadMain extends Fragment implements Callback<Partner> {
private static final String TAG = DownloadMain.class.getSimpleName();
private Button dloadPartners;
private Call callPartners;
public DownloadMain() {}
public DownloadMain newInstance() { return new DownloadMain(); }
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.download_main, container, false);
dloadPartners = (Button) view.findViewById(R.id.downloadPartners);
dloadPartners.setOnClickListener(btnListener);
callPartners = APIHelper.getApiService().getPartners();
return view;
}
Button.OnClickListener btnListener = (new Button.OnClickListener() {
#Override
public void onClick(View v) {
callPartners.clone().enqueue(DownloadMain.this);
}
});
#Override
public void onResponse(Call call, Response response) {
if(response.body() == null) {
try {
response.errorBody().string();
} catch (IOException e) {
e.printStackTrace();
}
Toast.makeText(getActivity(), "No Partners!", Toast.LENGTH_SHORT).show();
} else {
List<String> partners = (List<String>) response.body();
Log.d(TAG, "Number of partners received: " + partners.size());
Toast.makeText(getActivity(), "Partners downloaded!", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call call, Throwable t) {
}
}
This is all my code for getting Partners from web.
I'm getting this error on server side and can't resolve it:
No route matches [GET] "/partners.json/Partner"
QUESTION: Can someone look at this code and say what is wrong and why I'm not getting data from web and also how should I resolve this no route error?
change your get path like so
public interface APIService {
#GET("partners.json")
Call<List<Partner>> getPartners();
}
and remove that path from your base url.
public class APIHelper {
public static final String PARTNERS_URL = "https://part-of-url.herokuapp.com/";
public static APIService apiService;
public static APIService getApiService() {
if (apiService == null) {
Retrofit retrofit = new Retrofit.Builder().baseUrl(PARTNERS_URL)
.addConverterFactory(GsonConverterFactory.create()).build();
apiService = retrofit.create(APIService.class);
}
return apiService;
}
}

java.util.LinkedHashMap cannot be cast to DataList

I am trying to implement the server connections with retrofit library.
Everything seems fine but when I receive the data on success callback it crashes with the below exception.
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to aandroid.com.retrofitframework.requestData.DataList
at cuiserve.com.volleyframework.activity.RetrofitActivity$1.onDataReceived(RetrofitActivity.java:18)
at cuiserve.com.volleyframework.httpConnection.ConnectionHelper.success(ConnectionHelper.java:44)
at retrofit.CallbackRunnable$1.run(CallbackRunnable.java:45)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
here is the activity class making the server calls
public class RetrofitActivity extends SuperActivity {
private ConnectionHelper.ServerListener<DataList> httpListener = new ConnectionHelper.ServerListener<DataList>() {
#Override
public void onDataReceived(DataList data) {
hideProgressBar();
Log.d("ANSH",data.getBalance());
}
#Override
public void onErrorReceived(String errorMsg) {
hideProgressBar();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showProgressBar();
ConnectionHelper<DataList> helper = new ConnectionHelper<DataList>(HttpRequestConstant.LOGIN_REQUEST,httpListener);
helper.getResponse();
}
#Override
public View getLayoutResource() {
return null;
}
#Override
protected void internetAvailable() {
}
}
ConnectionHelper.class making the request
public class ConnectionHelper<T> implements Callback<T> {
private int requestType;
private ServerListener<T> listener;
public ConnectionHelper(int requestType, ServerListener listener) {
this.requestType = requestType;
this.listener = listener;
}
public void getResponse() {
switch (requestType) {
case HttpRequestConstant.LOGIN_REQUEST:
IServerConnection<T> connection = restAdapter.create(IServerConnection.class);
connection.login(this);
break;
}
}
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("http://www.json-generator.com/api")
.setLogLevel(RestAdapter.LogLevel.FULL)
.setConverter(new JacksonConverter(Mapper.get()))
.build();
#Override
public void success(T t, Response response) {
listener.onDataReceived(t);
// success callback false here with the exception
// as ClassCastException and says LinkedHashMap can not be cast to DataList(which i pass as class that the response has to be mapped to)
}
#Override
public void failure(RetrofitError error) {
}
public interface ServerListener<T> {
public void onDataReceived(T data);
public void onErrorReceived(String errorMsg);
}
}
The interface and the method with retrofit annotation
public interface IServerConnection<T> {
#GET(HttpRequestConstant.JACKSON_FETCH)
void login(Callback<T> cb);
}
The custom JacksonConverter which is my suspicion
public class JacksonConverter implements Converter {
private ObjectMapper mapper = new ObjectMapper();
public JacksonConverter(ObjectMapper objectMapper) {
this.mapper = objectMapper;
}
#Override
public Object fromBody(TypedInput body, Type type) throws ConversionException {
JavaType javaType = mapper.getTypeFactory().constructType(type);
try {
return mapper.readValue(body.in(), javaType);
} catch (IOException e) {
throw new ConversionException(e);
}
}
#Override
public TypedOutput toBody(Object object) {
try {
String charset = "UTF-8";
String json = mapper.writeValueAsString(object);
return new JsonTypedOutput(json.getBytes(charset));
} catch (IOException e) {
throw new AssertionError(e);
}
}
private static class JsonTypedOutput implements TypedOutput {
private final byte[] jsonBytes;
JsonTypedOutput(byte[] jsonBytes) {
this.jsonBytes = jsonBytes;
}
#Override
public String fileName() {
return null;
}
#Override
public String mimeType() {
return "application/json; charset=UTF-8";
}
#Override
public long length() {
return jsonBytes.length;
}
#Override
public void writeTo(OutputStream out) throws IOException {
out.write(jsonBytes);
}
}
}
and the DataList
package cuiserve.com.volleyframework.requestData;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* Created by ansh on 5/4/15.
*/
#JsonIgnoreProperties(ignoreUnknown = true)
public class DataList extends SomeClass{
private String _id;
private int index;
private String guid;
private boolean isActive;
private String balance;
private String picture;
private int age;
public String get_id() {
return _id;
}
public void set_id(String _id) {
this._id = _id;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public String getGuid() {
return guid;
}
public void setGuid(String guid) {
this.guid = guid;
}
public boolean isActive() {
return isActive;
}
public void setActive(boolean isActive) {
this.isActive = isActive;
}
public String getBalance() {
return balance;
}
public void setBalance(String balance) {
this.balance = balance;
}
public String getPicture() {
return picture;
}
public void setPicture(String picture) {
this.picture = picture;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Now the problem is when i do it without using generics(which i have done in the code) things work fine and don't give any exception but in case of generics it fails.
Why am I getting LinkedHashMap classCastException where nothing is related to that in my code.Please help.
By using a generic parameter the actual type information is completely lost to the runtime and cannot be inferred. It essentially ends up being the same as Object. When Gson sees that you want an Object type, it uses a Map to place the JSON information in. This way, if you re-serialize that object instance the data will be retained.
You cannot use generic interfaces with Retrofit. An exception has been added when you try to do this rather than letting it fail in this manner for the next release.
Here is what I do to handle such cases:
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;
public abstract class ModelCallback<Model> implements Callback<Object> {
Class classOfT;
public ModelCallback(Class modelClass){
this.classOfT = modelClass;
}
#Override
public void success(Object model, Response response) {
Gson gson = new Gson();
onSuccess((Model) gson.fromJson(gson.toJson(model),classOfT));
}
#Override
public void failure(RetrofitError error) {
onError(new Exception(error.getMessage()));
}
public abstract void onSuccess(Model model);
public abstract void onError(ClyngException e);
}

Categories

Resources