Getting exception while using REST API - android

I got an error of Expected Begin_ARRAY. but was BEGIN_OBJECTS at line 1 column
I am trying to get data from URL into recyclerview
api = RetrofitClient.getApiClient().create(Api.class);
Call<List<Courses>> call = api.getallcourse();
call.enqueue(new Callback<List<Courses>>()
{
#Override
public void onResponse(Call<List<Courses>> call, Response<List<Courses>> response) {
Toast.makeText(Dashboard.this, ""+response.toString(), Toast.LENGTH_SHORT).show();
courses = response.body();
recyclerAdapter = new RecyclerAdapter(courses);
recyclerView.setAdapter(recyclerAdapter);
}
#Override
public void onFailure(Call<List<Courses>> call, Throwable t) {
Toast.makeText(Dashboard.this, ""+t.toString(), Toast.LENGTH_SHORT).show();
}
});

Related

recycelrview adapter last item is not updating after deleting using retrofit , i am using interface because have to pass product id

Activity
#Override
protected void onResume() {
super.onResume();
getCartList();
}
private void getCartList() {
showProgressDialog();
Call<List<CartList>> call = api.getCartList(1);
call.enqueue(new Callback<List<CartList>>() {
#Override
public void onResponse(Call<List<CartList>> call, Response<List<CartList>> response) {
cartLists = response.body();
if (cartLists.size() == 0) {
tvCartEmpty.setVisibility(View.VISIBLE);
progressDialog.cancel();
} else {
addToCartAdapter.setData(cartLists);
productList.setAdapter(addToCartAdapter);
progressDialog.cancel();
}
}
#Override
public void onFailure(Call<List<CartList>> call, Throwable t) {
Toast.makeText(AddToCartActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void deleteItemID(int id) {
Call<CartList> deleteCall = api.deleteCartItem(id);
deleteCall.enqueue(new Callback<CartList>() {
#Override
public void onResponse(Call<CartList> call, Response<CartList> response) {
Log.d(TAG, "deleteItem by id" + response.code());
onResume();
}
#Override
public void onFailure(Call<CartList> call, Throwable t) {
Log.d(TAG, t.getMessage());
}
});
}
i mean last is deleting but not updating on the spot even though i called onresume in delete item method.
i have to open that activity again to see updted result
i hope i will get my query solved soon!
thanks
if you want i will upload inteface and adapter code. which i do not think necessary here.
Solution
just had to add this in response class
public void onResponse(Call<List<CartList>> call, Response<List<CartList>> response) {
cartLists = response.body();
if (cartLists.size() == 0) {
tvCartEmpty.setVisibility(View.VISIBLE);
tvCartItems.setText("0 items");
addToCartAdapter.setData(cartLists);
progressDialog.cancel();
} else {
addToCartAdapter.setData(cartLists);
productList.setAdapter(addToCartAdapter);
tvCartItems.setText(cartLists.size() + " Items");
progressDialog.cancel();
}
}
you don't need to call onResume() again.
instead of that you should use the following snippet:
cartLists.removeAt(id);
addToCartAdapter.notifyDataSetChanged();
your deleteItem function would look like below code:
#Override
public void deleteItemID(int id) {
Call<CartList> deleteCall = api.deleteCartItem(id);
deleteCall.enqueue(new Callback<CartList>() {
#Override
public void onResponse(Call<CartList> call, Response<CartList> response) {
Log.d(TAG, "deleteItem by id" + response.code());
cartLists.removeAt(id);
addToCartAdapter.notifyDataSetChanged();
}
#Override
public void onFailure(Call<CartList> call, Throwable t) {
Log.d(TAG, t.getMessage());
}
});

RecyclerView doesn't Update until Soft Keyboard is Open/Close

I have a Posts Feed (Something like Facebook News Feed) Activity and in it's layout I have an EditText, share Button at the top and a RecyclerView below it. The RecyclerView shows the Posts of all users by getting all the Posts from Server and binding data through Adapter in OnCreate Method.
When a User post something by typing some text in EditText and hit share Button, the data is sent to Server (I am using Retrofit) and upon Successful Response from Server I call the same function which call in OnCreate Method to show all Posts to update the RecyclerView.
The Problem I am facing is that the data is posted to Server, but the Layout only gets updated only when I press the back button to Hide/Close the Keyboard after typing or Show/Open the Keyboard by tapping the EditText.
Following is Some of the Code for better understanding:
Here I Send Request to Server when User Post something:
Call<CreatePost> call = mAPIService.sharePost(apiKey, post_description);
call.enqueue(new Callback<CreatePost>() {
#Override
public void onResponse(#NonNull Call<CreatePost> call, #NonNull Response<CreatePost> response) {
boolean error = response.body().getError();
if (!error) {
displayFeedPosts();
}
}
#Override
public void onFailure(#NonNull Call<CreatePost> call, #NonNull Throwable t) {
Log.d(TAG, "Error: " + t.getMessage());
}
});
Here Is displayFeedPosts Method:
private void displayFeedPosts() {
Call<FeedPosts> call = mAPIService.displayFeedPosts(apiKey);
call.enqueue(new Callback<FeedPosts>() {
#Override
public void onResponse(#NonNull Call<FeedPosts> call, #NonNull Response<FeedPosts> response) {
boolean error = response.body().getError();
if (!error) {
ArrayList<Post> feedPosts = response.body().getPosts();
for (Post post : feedPosts) {
mTripFeedPostUserNames.add(post.getFirstName() + " " + post.getLastName());
mTripFeedPostTime.add(post.getPostDatetime());
mTripFeedPostContent.add(post.getPostDescription());
}
}
}
#Override
public void onFailure(#NonNull Call<FeedPosts> call, #NonNull Throwable t) {
Log.d(TAG, "Error: " + t.getMessage());
}
});
initRecyclerView();
}
private void initRecyclerView() {
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, true);
RecyclerView recyclerView = findViewById(R.id.trip_feed_recycler_view);
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setLayoutManager(layoutManager);
mTripFeedPostRecyclerViewAdapter = new TripFeedPostRecyclerViewAdapter(this, mTripFeedPostProfileImages, mTripFeedPostUserNames, mTripFeedPostTime, mTripFeedPostContent, mTripFeedPostImages, mTripFeedPostID);
recyclerView.setAdapter(mTripFeedPostRecyclerViewAdapter);
}
PS: I am new to Android, I apologise if I have done things the wrong way. Your suggestions are Welcomed.
Note: The same Question has been asked regarding ListView here and here but it doesn't solved my problem
I solved the above problem with the help of Arsalan Khan Answer.
Actually the initRecyclerView() was not executing outside the onResponse() method. Including it inside the onResponse() method and using notifyDataSetChanged() instead of initRecyclerView() solved the problem.
The solution to data being populated twice I solved it by modifying the displayFeedPosts() in the following way:
private void updateFeedPosts() {
Call<FeedPosts> call = mAPIService.displayFeedPosts(apiKey);
call.enqueue(new Callback<FeedPosts>() {
#Override
public void onResponse(#NonNull Call<FeedPosts> call, #NonNull Response<FeedPosts> response) {
boolean error = response.body().getError();
if (!error) {
mTripFeedPostProfileImages.clear();
mTripFeedPostUserNames.clear();
mTripFeedPostTime.clear();
mTripFeedPostContent.clear();
mTripFeedPostImages.clear();
mTripFeedPostID.clear();
mTripFeedPostRecyclerViewAdapter.notifyDataSetChanged();
ArrayList<Post> feedPosts = response.body().getPosts();
for (Post post : feedPosts) {
mTripFeedPostProfileImages.add(post.getProfilePicture());
mTripFeedPostUserNames.add(post.getFirstName() + " " + post.getLastName());
mTripFeedPostTime.add(post.getPostDatetime());
mTripFeedPostContent.add(post.getPostDescription());
mTripFeedPostImages.add(post.getPostImagePath());
mTripFeedPostID.add(post.getPostTripfeedId());
}
mTripFeedPostRecyclerViewAdapter.notifyDataSetChanged();
}
}
#Override
public void onFailure(#NonNull Call<FeedPosts> call, #NonNull Throwable t) {
Log.d(TAG, "Error: " + t.getMessage());
}
});
}
I cleared the Adapter Data before populating it again with updated data.
I hope my answer will help someone having the same problem.
PS: I know I am not using my Adapter Model in correct way, I can use only one ArrayList for all the values, I'll modify it later right now I am focusing on the main functions.
should call initRecyclerView here:
private void displayFeedPosts() {
Call<FeedPosts> call = mAPIService.displayFeedPosts(apiKey);
call.enqueue(new Callback<FeedPosts>() {
#Override
public void onResponse(#NonNull Call<FeedPosts> call, #NonNull Response<FeedPosts> response) {
boolean error = response.body().getError();
if (!error) {
ArrayList<Post> feedPosts = response.body().getPosts();
for (Post post : feedPosts) {
mTripFeedPostUserNames.add(post.getFirstName() + " " + post.getLastName());
mTripFeedPostTime.add(post.getPostDatetime());
mTripFeedPostContent.add(post.getPostDescription());
}
initRecyclerView();
}
}
#Override
public void onFailure(#NonNull Call<FeedPosts> call, #NonNull Throwable t) {
Log.d(TAG, "Error: " + t.getMessage());
}
});
}
private void initRecyclerView() {
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, true);
RecyclerView recyclerView = findViewById(R.id.trip_feed_recycler_view);
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setLayoutManager(layoutManager);
mTripFeedPostRecyclerViewAdapter = new TripFeedPostRecyclerViewAdapter(this, mTripFeedPostProfileImages, mTripFeedPostUserNames, mTripFeedPostTime, mTripFeedPostContent, mTripFeedPostImages, mTripFeedPostID);
recyclerView.setAdapter(mTripFeedPostRecyclerViewAdapter);
mTripFeedPostRecyclerViewAdapter.notifyDataSetChanged();
}

Using retrofit to call two APIs in same class

I am having problem while calling two different APIs. There is no problem while calling first API using retrofit but when it reaches second retrofit call, there occurs error. Following is my code.
//for first retrofit call:
apiInterface = ApiClient.getApiClient().create(LekhaDrillInterface.class);
Call<LekhaDrillModel> call = apiInterface.getData(id, memberId);
call.enqueue(new Callback<LekhaDrillModel>() {
#Override
public void onResponse(Call<LekhaDrillModel> call, Response<LekhaDrillModel> response) {
posts = Collections.singletonList(response.body());
adapter = new LekhaBolpatraDrillAdapter(posts, getApplicationContext());
rvLekhaDrill.setAdapter(adapter);
progressBar.setVisibility(View.GONE);
}
#Override
public void onFailure(Call<LekhaDrillModel> call, Throwable t) {
Log.e("error", t.getMessage());
}
});
here is no error and data is set in adapter
//2nd retrofit call
private void callRetrofitListData(){
pariyojanaInterfaces = ApiClient.getApiClient().create(PariyojanaInterface.class);
Log.e("memberIDIDID", String.valueOf(memberId));
Call <Data> call1 = pariyojanaInterfaces.getData(memberId);
call1.enqueue(new Callback<Data>() {
#Override
public void onResponse(Call<Data> call, Response<Data> response) {
datas = (List<Data>) response.body();
if (response.body()!=null){
Log.d("jchhec","chekc");
}
itemListAdapter = new ItemListAdapter(getApplicationContext(), datas);
rv.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
rv.setAdapter(itemListAdapter);
}
#Override
public void onFailure(Call<Data> call1, Throwable t) {
Log.e("error", t.getMessage());
}
});
}
the error is in the line
Call <Data> call1 = pariyojanaInterfaces.getData(memberId);
and the error is
Unable to create call adapter for interface retrofit2.Call for method PariyojanaInterface.getData
PariyojanaInterface.java
public interface PariyojanaInterface { #POST("projectBudget/pariyojanaListForMobile") Call getData(#Query("memberId") int memberId);
Can anybody please help me fix this problem?
First you must change PariyojanaInterface.java to
public interface PariyojanaInterface {
#POST("projectBudget/pariyojanaListForMobile") Call<List<Data>> getData(#Query("memberId") int memberId);
}
I Dont khow what your Data is, so you must replace List<Data> with List<yourData>
And you must change new Callback<Data> To new Callback<List<Data>

Android display boolean from Retrofit as false ALWAYS

In my Main Activity i execute SincronizacionDb to compare the data between SQLite and the MYSQL Server, however the json_array retrieved works fine, it's show true or false if the data it's different from the server, but in the APP, this value seems to be always false.
SincronizacionDb
private void sincronizacionDB() {
if (dbCheck(MainActivity.this, "beneficiosColaborador.db")) {
int size = sqLiteHandler.getLastIdBeneficio();
Call<VersionDb> versionDb = restManager.getApiService().checkServerDatabaseVersion(size);
versionDb.enqueue(new Callback<VersionDb>() {
#Override
public void onResponse(Call<VersionDb> call, Response<VersionDb> response) {
Log.e("RESPONSE", "CALLING ON RESPONSE");
VersionDb version = response.body();
isOutdate = version.getEstado();
Log.i("VERSION", "RESPUESTA" + version.getEstado()); // Get the value from GSon(TRUE, FALSE) WORKS PERFECT
}
#Override
public void onFailure(Call<VersionDb> call, Throwable t) {
Log.e("error", t.getMessage());
}
});
Log.e("outdate","" + isOutdate); // ALWAYS FALSE
if (isOutdate) {
sqLiteHandler.deleteBeneficio();
Log.e("Beneficios", "Se han eliminado los beneficios viejos");
Call<List<Beneficios>> callBeneficios = restManager.getApiService().getListadoBeneficios();
callBeneficios.enqueue(new Callback<List<Beneficios>>() {
#Override
public void onResponse(Call<List<Beneficios>> call, Response<List<Beneficios>> response) {
List<Beneficios> beneficioData = response.body();
sqLiteHandler.addListBeneficios(beneficioData);
}
#Override
public void onFailure(Call<List<Beneficios>> call, Throwable t) {
Log.e("error", t.getMessage());
//Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
}else{
Call<List<Beneficios>> callBeneficios = restManager.getApiService().getListadoBeneficios();
callBeneficios.enqueue(new Callback<List<Beneficios>>() {
#Override
public void onResponse(Call<List<Beneficios>> call, Response<List<Beneficios>> response) {
List<Beneficios> beneficioData = response.body();
sqLiteHandler.addListBeneficios(beneficioData);
}
#Override
public void onFailure(Call<List<Beneficios>> call, Throwable t) {
Log.e("error", t.getMessage());
//Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
}
and the Results i got in the ANDROID MONITOR
08-11 08:39:31.417 13618-13618/com.freelance.crdzbird_dev.clarobadge D/SQLiteHandler: Fetching LAST ROW from Sqlite: 213
08-11 08:39:31.617 13618-13618/com.freelance.crdzbird_dev.clarobadge E/outdate: false
08-11 08:39:31.867 13618-13618/com.freelance.crdzbird_dev.clarobadge E/RESPONSE: CALLING ON RESPONSE
08-11 08:39:31.867 13618-13618/com.freelance.crdzbird_dev.clarobadge I/VERSION: RESPUESTA true
Please someone explain me how to avoid this error :(
It seems that you are doing an asynchrounous call in here :
versionDb.enqueue(new Callback<VersionDb>() {
#Override
public void onResponse(Call<VersionDb> call, Response<VersionDb> response) {
Log.e("RESPONSE", "CALLING ON RESPONSE");
VersionDb version = response.body();
isOutdate = version.getEstado();
Log.i("VERSION", "RESPUESTA" + version.getEstado()); // Get the value from GSon(TRUE, FALSE) WORKS PERFECT
}
#Override
public void onFailure(Call<VersionDb> call, Throwable t) {
Log.e("error", t.getMessage());
}
});
And your value of isOutdate is initialized at false, so it will be always false since it executes the check before returning from the service.
So either wait for your callback or use the synchronized method execute in retrofit.

Save asynchronous retrofit response

I am using retrofit:2.1.0 and I am trying to save the response returned to my own POJO (UserProfile) but I can't seem to access the POJO, I assign the response to, outside of the callbacks.
So, in this call below, I want to have access to UserProfile outside of this call.
//adding `UserProfile userProfile;` outside of Call didn't help either
call.enqueue(new Callback<UserProfile>() {
#Override
public void onResponse(Call<UserProfile> call, Response<UserProfile> response) {
if (response.isSuccessful()) {
UserProfile userProfile = response.body();
}
}
#Override
public void onFailure(Call<UserProfile> call, Throwable t) {
//do something
}
});
//here userProfile is null and hence can't get status
Log.d(TAG, "Status outside of Call is: " + userProfile.getStatus());
New approach, same result
private List<UserProfile> userProfileList = new ArrayList<>();
call.enqueue(new Callback<UserProfile>() {
#Override
public void onResponse(Call<UserProfile> call, Response<UserProfile> response) {
if (response.isSuccessful()) {
UserProfile userProfile = response.body();
userProfileList.add(userProfile);
}
}
#Override
public void onFailure(Call<UserProfile> call, Throwable t) {
//do something
}
});
And this one gets fired even before callback and hence is null
if(userProfileList.size() > 0) {
for(UserProfile userProfile : userProfileList) {
Log.d(TAG, "Status is: " + userProfile.getStatus());
}
} else {
Log.d(TAG, "YakkerProfileList is NULL");
}
I added a setter in onResponse() which allowed me to use the response object elsewhere in the code like so:
#Override
public void onResponse(Call<UserProfile> call, Response<UserProfile> response) {
if (response.isSuccessful()) {
UserProfile userProfile = response.body();
//elsewhere in the code, I can read the value from this method
setUserProfile(userProfile.getStatus());
}
}

Categories

Resources