Using retrofit to call two APIs in same class - android

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>

Related

Getting exception while using REST API

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();
}
});

Retrofit 2 How to Make Same Request Multiple Times

public void makeGetRequest() {
Retrofit.Builder builder = new Retrofit.Builder().baseUrl("https://desolate-beach-17272.herokuapp.com");
Retrofit retrofit = builder.build();
RetrofitInterface retrofitInterface = retrofit.create(RetrofitInterface.class);
Call<ResponseBody> call = retrofitInterface.downloadFileByUrl("downloadFile/beach.jpg");
call.enqueue(new Callback<ResponseBody>() {
#SuppressLint("StaticFieldLeak")
// returns the response if everything is okay
#Override
public void onResponse(Call<ResponseBody> call, final Response<ResponseBody> response) {
try {
Log.d("Success" , " " + response.body().bytes().length);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.d("FAIL", "oops");
}
});
I have this code and it makes a get request to my server with the async method. What I want is to make the same request multiple times. For example, I want to make get request 100 times. I don't want to use observables or other external libraries if possible. Is there anyone who can help me with that?
You can make call multiple times just see the below code where I have used methods for this purpose. In onResponse method after performing operation on data you get from server you can make another call to the same API by using a variable sizeOfCall and decrementing it untill it equals to zero. Below is the full code for it.
public class RequestActivity extends AppCompatActivity {
int sizeOfCall = 100;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_request);
callAPI();
}
private void callAPI(){
Retrofit.Builder builder = new Retrofit.Builder().baseUrl("https://desolate-beach-17272.herokuapp.com");
Retrofit retrofit = builder.build();
RetrofitInterface retrofitInterface = retrofit.create(RetrofitInterface.class);
Call<ResponseBody> call = retrofitInterface.downloadFileByUrl("downloadFile/beach.jpg");
// Call API
makeGetRequest(call);
}
private void makeGetRequest(Call<ResponseBody> call) {
call.enqueue(new Callback<ResponseBody>() {
#SuppressLint("StaticFieldLeak")
// returns the response if everything is okay
#Override
public void onResponse(Call<ResponseBody> call, final Response<ResponseBody> response) {
try {
Log.d("Success", " " + response.body().bytes().length);
// Perform your operations here and call API againg after that
sizeOfCall--;
if (sizeOfCall > 0) {
callAPI();
} else {
// No more calls needed
}
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.d("FAIL", "oops");
}
});
}
}
Create a broadcast reciever and put your retrofit request in that. Now call it using alarm manager.
public class YourBroadCastReciever extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
yourRetrofitCode();
}
private void yourRetrofitCode(){
Retrofit.Builder builder = new Retrofit.Builder().baseUrl("https://desolate-beach-17272.herokuapp.com");
Retrofit retrofit = builder.build();
RetrofitInterface retrofitInterface = retrofit.create(RetrofitInterface.class);
Call<ResponseBody> call = retrofitInterface.downloadFileByUrl("downloadFile/beach.jpg");
call.enqueue(new Callback<ResponseBody>() {
#SuppressLint("StaticFieldLeak")
// returns the response if everything is okay
#Override
public void onResponse(Call<ResponseBody> call, final Response<ResponseBody> response) {
try {
Log.d("Success" , " " + response.body().bytes().length);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.d("FAIL", "oops");
}
});
}
}
now call using this code :
Intent sendDeviceInfoIntent = new Intent(this, YourBroadCastReciever.class);
PendingIntent yourintent= PendingIntent.getBroadcast(this, 0, sendDeviceInfoIntent, 0);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime()+1000, 60000, yourintent);
so that every 5 min this will call your broadcast reciever and this will also works in background

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();
}

Android - Retrofit does not display data

I'm trying to learn Retrofit making simple weather app and I have some problem. I made two methods to display data in Activity and method does not work outside onCreate, but second one in works. In Android Profiler I can see JSON logs, but still I don't see anything in Activity. What's the problem?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(WeatherAPI_Interface.API_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
WeatherAPI_Interface weatherAPIInterface = retrofit.create(WeatherAPI_Interface.class);
latitude = 37.8267;
longitude = -122.4233;
Call<Currently> call = weatherAPIInterface.getWeather(latitude, longitude);
call.enqueue(new Callback<Currently>() {
#Override
public void onResponse(#NonNull Call<Currently> call, #NonNull Response<Currently> response) {
temp_textview.setText(String.valueOf(response.body().getCurrently().getTemperature()));
city_textview.setText(response.body().getTimezone());
image_View.setImageResource(Integer.parseInt(response.body().getCurrently().getIcon()));
}
#Override
public void onFailure(#NonNull Call<Currently> call, #NonNull Throwable t) {
}
});
}
#Override
public void getCurrentWeather(final Currently currently) {
latitude = 37.8267;
longitude = -122.4233;
NetworkClient.getInstance().getWeather(latitude, longitude).enqueue(new Callback<Currently>() {
#Override
public void onResponse(#NonNull Call<Currently> call, #NonNull Response<Currently> response) {
weather_textview.setText((CharSequence) response.body().getCurrently().getSummary());
pressure_textview.setText((CharSequence) response.body().getDaily().getData());
temp_textview.setText(String.valueOf(currently.getCurrently().getTemperature()));
Log.d(TAG, "City" + currently.getLatitude());
}
#Override
public void onFailure(Call<Currently> call, Throwable t) {
Log.d(TAG, "Failed" + t.getMessage());
}
});
}
public class NetworkClient {
private static WeatherAPI_Interface service;
public static WeatherAPI_Interface getInstance() {
if (service == null) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(WeatherAPI_Interface.API_URL)
.build();
service = retrofit.create(WeatherAPI_Interface.class);
return service;
}
else {
return service;
}
}
}
You didn't call the function how can it work?
when the activity starts it'll run the code in OnCreate ( and any call in it) only, so to run any function outside it you need to call it.

How can I use the Retrofit response outside the OnResponse function?

I want to get the retrofit response list and use it outside the OnResponse function, but went I try to do it I'm always getting a null object.
Here is my source code
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<ActivitiesResponse> call = apiService.getUserActivities(id);
call.enqueue(new Callback<ActivitiesResponse>() {
// If success
#Override
public void onResponse(Call<ActivitiesResponse>call, Response<ActivitiesResponse> response) {
list = response.body().getActivities();// I'm getting a not null response
}
// If failed
#Override
public void onFailure(Call<ActivitiesResponse>call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
});
//When I try to use the list here I'm getting a null object
Requests are async, so when you try to return a value, the request is likely not done yet so you cannot use it outside of the request. If you want to return values from the request use callback interfaces.
Change your code to a method and pass a callback parameter
Example
public void doRequest(final ApiCallback callback) {
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<ActivitiesResponse> call = apiService.getUserActivities(id);
call.enqueue(new Callback<ActivitiesResponse>() {
// If success
#Override
public void onResponse(Call<ActivitiesResponse>call, Response<ActivitiesResponse> response) {
list = response.body().getActivities();
callback.onSuccess(list); // pass the list
}
// If failed
#Override
public void onFailure(Call<ActivitiesResponse>call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
});
}
public interface ApiCallback{
void onSuccess(ArrayList<YOURTYPE> result);
}
Example usage in onResume(), basically you can do this anywhere you want:
public void onResume(){
super.onResume();
doRequest(new ApiCallback(){
#Override
public void onSuccess(ArrayList<YOURTYPE> result){
//do stuff here with the list from the request
}
});
}
Let me know if this fits your needs
Because onResponse() runs asynchronously. You can not get its value like that.
You should call the method which uses list value inside onResponse().
For example.
call.enqueue(new Callback<ActivitiesResponse>() {
// If success
#Override
public void onResponse(Call<ActivitiesResponse>call, Response<ActivitiesResponse> response) {
list = response.body().getActivities();// I'm getting a not null response
yourMethod();
}
// If failed
#Override
public void onFailure(Call<ActivitiesResponse>call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
});
private void yourMethod() {
// list is used somewhere here
}

Categories

Resources