In my application i want use Retrofit2 library for requests and i want set dynamically response model, i don't want set model into interface model!
For example :
My interface method is :
#GET("api/server?mode=supports")
Call<SupportListResponse> getSupport_List(#Header("jwt") String token);
I don't want set SupportListResponse into Call<> , i want set this model dynamically from Activity/Fragment class!
How can i set general model class instead of SupportListResponse ?
My activity full code :
public class TimerRecyclerActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private ProgressBar timerProgressBar;
private List<Today> model = new ArrayList<>();
private Adapter adapter;
private ApiInterface api;
private LinearLayoutManager layoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timer_recycler);
api = ApiClient.getClient().create(ApiInterface.class);
adapter = new Adapter(getApplicationContext(), model);
adapter.setHasStableIds(true);
recyclerView = findViewById(R.id.timerRecyclerView);
timerProgressBar = findViewById(R.id.timerProgressBar);
layoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
Call<AuctionsListResponse> call = api.getMainAuctions("", 1, 10);
call.enqueue(new Callback<AuctionsListResponse>() {
#Override
public void onResponse(Call<AuctionsListResponse> call, Response<AuctionsListResponse> response) {
if (response.isSuccessful()) {
if (response.body().getRes() != null) {
if (response.body().getRes().getToday().size() > 0) {
timerProgressBar.setVisibility(View.GONE);
model.clear();
model.addAll(response.body().getRes().getToday());
adapter.notifyDataSetChanged();
}
}
}
}
#Override
public void onFailure(Call<AuctionsListResponse> call, Throwable t) {
}
});
}
}
How can i it?
Do Some modification in your code
#GET("api/server?mode=supports")
Call<ResponseBody> getSupport_List(#Header("jwt") String token);
while getting retrofit object
public static Retrofit getWorkbook() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(ScalarsConverterFactory.create())
.build();
}
return retrofit;
}
in main Activity Retrofit
private void gettingResponseFromRetrofit() {
ApiInterface api = ApiClient.getWhatsNew().create(ApiInterface.class);
Call<ResponseBody> call = api.getSupport_List("", 1, 10);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(#NonNull Call<ResponseBody> call, #NonNull Response<ResponseBody> response) {
if (response.isSuccessful()) {
try {
// here you will get the response
// do your stuff
} catch (Exception e) {
e.printStackTrace();
}
} else {
Toast.makeText(getApplicationContext(), "Some Error Occur", Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(#NonNull Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});
}
Related
I am using retrofit2 to enqueue multiple recyclerviews. It works great on one recyclerview but when i go to enqueue a second one with a different category it doesnt work.
I have tried making a second onresponse method, i cant think of any other way of doing it
Call<MovieResponse> call = apiInterface.getTopRatedMovies(API_KEY);//This one is working!
Call<MovieResponse> call1 = apiInterface.getNowPlayingMovies(API_KEY); //This is what i what to implement
Here is the code
Call<MovieResponse> call = apiInterface.getTopRatedMovies(API_KEY);
call.enqueue(new Callback<MovieResponse>() {
#Override
public void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {
int statuscode =response.code();
List<Movie> movies = response.body().getResults();
recyclerView.setAdapter(new MoviesAdapter(movies, R.layout.movie_item, getContext()));
recyclerView1.setAdapter(new MoviesAdapter(movies, R.layout.movie_item, getContext())); //this works but not with the NowPlayingMovies, tested to see if it was the other recyclerview
}
#Override
public void onFailure(Call<MovieResponse> call, Throwable t) {
//Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
If you dont prefer to use RxJava then you can use following solution:
Call<MovieResponse> call = apiInterface.getTopRatedMovies(API_KEY);
call.enqueue(new Callback<MovieResponse>() {
#Override
public void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {
int statuscode =response.code();
List<Movie> movies = response.body().getResults();
recyclerView.setAdapter(new MoviesAdapter(movies, R.layout.movie_item, getContext()));
secondAPICall();
}
#Override
public void onFailure(Call<MovieResponse> call, Throwable t) {
//Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
public void secondAPICall(){
call1.enqueue(new Callback<MovieResponse>() {
#Override
public void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {
int statuscode =response.code();
List<Movie> movies = response.body().getResults();
recyclerView1.setAdapter(new MoviesAdapter(movies, R.layout.movie_item, getContext()));
}
#Override
public void onFailure(Call<MovieResponse> call, Throwable t) {
//Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
Basically this it the code structure, I would like to know how i can modify my codes so that I can get the value inside onResponse and returning it. As of now, my mainReply variable return "(blank)" but im expecting it to pass the data in the arraylist called details inside my onResponse segment. Rest assure, there are values returned as I have checked, but i just cant get the value to be passed out of the onResponse segment.
I have checked for alternatives and they mentioned to use interface. However, I do not know how to modify my codes to use the solution that mentioned interface and use of callBacks.
public class MainActivity extends AppCompatActivity {
EditText et_message;
FloatingActionButton fab_send;
API api;
ListView list_view_conversation;
List<ChatModel> list_chat = new ArrayList<>();
RevealDetailsCallbacks callback;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_message = (EditText) findViewById(R.id.et_message);
fab_send = (FloatingActionButton) findViewById(R.id.fab_send);
list_view_conversation = (ListView) findViewById(R.id.list_view_conversation);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
api = retrofit.create(API.class);
fab_send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//this method ultimately is to get response and send back to user
String s = et_message.getText().toString();
ChatModel model = new ChatModel(s, true);
list_chat.add(model);
new retrieveDetails().execute(list_chat);
et_message.setText("'");
}
});
}
public class retrieveDetails extends AsyncTask<List<ChatModel>, Void, String> {
String text = et_message.getText().toString();
String mainReply = "";
List<ChatModel> models;
List<String> details = new ArrayList<String>();
#Override
public String doInBackground(List<ChatModel>[] lists) {
Call<List<Patient>> call = api.getPatients();
models = lists[0];
call.enqueue(new Callback<List<Patient>>() {
public String reply;
#Override
public void onResponse(Call<List<Patient>> call, Response<List<Patient>> response) {
List<Patient> patients = response.body();
for (int i = 0; i < patients.size(); i++) {
if (patients.get(i).getNric().equals(text)) {
details.add("Name: " + patients.get(i).getName() + "\nNRIC: " + patients.get(i).getNric()
+ "\nDOB: " + patients.get(i).getDob() + "\nContact No: " + patients.get(i).getContactno());
}
}
this.mainReply = details.get(0);
Log.i("Here Log i", reply);
}
#Override
public void onFailure(Call<List<Patient>> call, Throwable t) {
Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
return mainReply;//I want to reply with the data added into the details arraylist in the onResponse segment
}
#Override
public void onPostExecute(String s) {
ChatModel chatModel = new ChatModel(s, false);
models.add(chatModel);
CustomAdapter adapter = new CustomAdapter(models, getApplicationContext());
list_view_conversation.setAdapter(adapter);
}
}
}
If you wanted to modify your existing code, you would add an interface like the one I added up top (RevealDetailsCallbacks), pass it into the asynctask constructor, and run it. The code would look like this:
public class MainActivity extends AppCompatActivity {
//Interface callback here
interface RevealDetailsCallbacks {
public void getDataFromResult(List<String> details);
}
EditText et_message;
FloatingActionButton fab_send;
API api;
ListView list_view_conversation;
List<ChatModel> list_chat = new ArrayList<>();
RevealDetailsCallbacks callback;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_message = (EditText) findViewById(R.id.et_message);
fab_send = (FloatingActionButton) findViewById(R.id.fab_send);
list_view_conversation = (ListView) findViewById(R.id.list_view_conversation);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
this.callback = new RevealDetailsCallbacks() {
#Override
public void getDataFromResult(List<String> details) {
//Do stuff here with the returned list of Strings
}
};
api = retrofit.create(API.class);
fab_send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//this method ultimately is to get response and send back to user
String s = et_message.getText().toString();
ChatModel model = new ChatModel(s, true);
list_chat.add(model);
new retrieveDetails(callback).execute(list_chat);
et_message.setText("'");
}
});
}
public class retrieveDetails extends AsyncTask<List<ChatModel>, Void, String> {
String text = et_message.getText().toString();
String mainReply = "";
List<ChatModel> models;
List<String> details = new ArrayList<String>();
private RevealDetailsCallbacks listener;
retrieveDetails(RevealDetailsCallbacks listener){
this.listener = listener;
}
#Override
public String doInBackground(final List<ChatModel>[] lists) {
Call<List<Patient>> call = api.getPatients();
models = lists[0];
call.enqueue(new Callback<List<Patient>>() {
public String reply;
#Override
public void onResponse(Call<List<Patient>> call, Response<List<Patient>> response) {
List<Patient> patients = response.body();
for (int i = 0; i < patients.size(); i++) {
if (patients.get(i).getNric().equals(text)) {
details.add("Name: " + patients.get(i).getName() + "\nNRIC: " + patients.get(i).getNric()
+ "\nDOB: " + patients.get(i).getDob() + "\nContact No: " + patients.get(i).getContactno());
}
}
this.mainReply = details.get(0);
Log.i("Here Log i", reply);
if(listener != null) {
listener.getDataFromResult(details);
}
}
#Override
public void onFailure(Call<List<Patient>> call, Throwable t) {
//Don't make a toast here, it will throw an exception due to it being in doInBackground
//Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
return mainReply;//I want to reply with the data added into the details arraylist in the onResponse segment
}
#Override
public void onPostExecute(String s) {
ChatModel chatModel = new ChatModel(s, false);
models.add(chatModel);
CustomAdapter adapter = new CustomAdapter(models, getApplicationContext());
list_view_conversation.setAdapter(adapter);
}
}
}
However, there is no need for asynctask here since you are running Retrofit and calling .enqueue, which runs on a background thread. A simpler version would look like this:
public class MainActivity extends AppCompatActivity {
//Interface callback here
interface RevealDetailsCallbacks {
public void getDataFromResult(List<String> details);
}
//Keep your same variables here
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Same setup here
this.callback = new RevealDetailsCallbacks() {
#Override
public void getDataFromResult(List<String> details) {
//Do stuff here with the returned list of Strings
}
};
fab_send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Same setup here, then call the method
makeWebCalls();
}
});
}
private void makeWebCalls(){
Call<List<Patient>> call = api.getPatients();
models = lists[0];
call.enqueue(new Callback<List<Patient>>() {
#Override
public void onResponse(Call<List<Patient>> call, Response<List<Patient>> response) {
//Run your response code here. When done, pass to the callback
}
#Override
public void onFailure(Call<List<Patient>> call, Throwable t) {
Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
You can just enqueue the Retrofit call immediately in the OnClick and handle its response there
fab_send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final String text = et_message.getText().toString();
// if you're trying to filter data, add a parameter to getPatients()
api.getPatients().enqueue(new Callback<List<Patient>>() {
#Override
public void onResponse(Call<List<Patient>> call, Response<List<Patient>> response) {
// Here you have a full list of patients
final List<Patient> patients = response.body();
// adapter = new PatientAdapter(MainActivity.this, patients);
// mListView.setAdapter(adapter);
}
I would like to be able to get values from a server by using their API, to be able to do that I have to send an API-key and an API-Code in the header, I have tried with Retrofit to be able to use annotations but with no luck, so if anyone can look through the code and point me in the right direction, I would appreciate it!
Below I will add some code examples:
APIService
public interface APIService {
#GET("/temperature")
#Headers({"api-key: "my api key", "code: "my-api-code"})
Call<Post> getTemperature();
ApiUtils
public class ApiUtils {
private ApiUtils() {}
public static final String BASE_URL = "my url";
public static APIService getAPIService() {
return RetrofitClient.getClient(BASE_URL).create(APIService.class);
}
Retrofit Client
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
Main Activity
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private TextView mResponseTv;
private APIService mAPIService;
#NonNull
private CompositeDisposable mDisposables;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText titleEt = (EditText) findViewById(R.id.et_title);
final EditText bodyEt = (EditText) findViewById(R.id.et_body);
Button submitBtn = (Button) findViewById(R.id.btn_submit);
mResponseTv = (TextView) findViewById(R.id.tv_response);
mAPIService = ApiUtils.getAPIService();
mDisposables = new CompositeDisposable();
submitBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String title = titleEt.getText().toString().trim();
String body = bodyEt.getText().toString().trim();
if(!TextUtils.isEmpty(title) && !TextUtils.isEmpty(body)) {
sendPost(title, body);
}
}
});
}
public void showErrorMessage() {
Toast.makeText(this, R.string.mssg_error_submitting_post, Toast.LENGTH_SHORT).show();
}
public void getTemperature() {
mAPIService.getTemperature().enqueue(new Callback<Post>() {
#Override
public void onResponse(Call<Post> call, Response<Post> response) {
if (response.isSuccessful()) {
showResponse(response.body().toString());
}
}
#Override
public void onFailure(Call<Post> call, Throwable t) {
showErrorMessage();
}
});
}
If you use Retrofit 2 you can try this
public interface APIService {
#GET("/temperature")
Call<Post> getTemperature(#Header("api-key") String my_api_key, #Header("code") String my-api-code);
And pass codes in your call
I have successfully made a call to FlickR using Retrofit, and the result is returning several pages.
However, it appears that my response.body() is only returning page 1. My thought was to iterate through all of the pages to obtain the results, but I am unsure of how to access the subsequent pages after 1:
mRequestButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mQuery = mSearchTerm.getText().toString();
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.flickr.com/services/rest/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiInterface apiInterface = retrofit.create(ApiInterface.class);
Call<Flicker> call = apiInterface.getImages(mQuery);
call.enqueue(new Callback<Flicker>() {
#Override
public void onResponse(Call<Flicker> call, Response<Flicker> response) {
Log.v("RESPONSE_CALLED", "ON_RESPONSE_CALLED");
String didItWork = String.valueOf(response.isSuccessful());
Log.v("SUCCESS?", didItWork);
Log.v("RESPONSE_CODE", String.valueOf(response.code()));
Flicker testResponse = response.body();
Log.v("RESPONSE_BODY", "response:" + testResponse);
String total = response.body().getPhotos().getTotal().toString();
Log.v("Total", total);
List<Photo> photoResults = response.body().getPhotos().getPhoto();
int numberOfPages = response.body().getPhotos().getPages();
for (int i = 0; i < numberOfPages; i++) {
for (Photo photo : photoResults) {
if (photo.getUrl_m() != null) {
Log.v("PHOTO_URL:", photo.getUrl_m()
);
}
}
}
}
#Override
public void onFailure(Call<Flicker> call, Throwable t) {
}
});
}
});
mSearchButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent toSearch = new Intent(MainActivity.this, FlickRActivity.class);
startActivity(toSearch);
}
});
API Interface
public interface ApiInterface {
#GET("?method=flickr.photos.search&api_key=1c448390199c03a6f2d436c40defd90e&format=json&nojsoncallback=1&extras=url_m")
Call<Flicker> getImages(#Query("text") String query);
}
Search results for "lebron james":
I have successfully determined how to make a call to the FlickR API. However, I am having difficulty determining how I search all of the FlickR photos based on a search term entered by the user.
I believe the search term should be entered into the "tags" component of the FlickR API, however I do not know how to link my Edit Text variable (mQuery) to the FlickR API tag:
public class MainActivity extends AppCompatActivity {
private EditText mSearchTerm;
private Button mRequestButton;
private String mQuery;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSearchTerm = (EditText) findViewById(R.id.ediText_search_term);
mRequestButton = (Button) findViewById(R.id.request_button);
mRequestButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mQuery = mSearchTerm.getText().toString();
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.flickr.com/services/rest/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiInterface apiInterface = retrofit.create(ApiInterface.class);
Call<List<Photo>> call = apiInterface.getPhotos(mQuery);
call.enqueue(new Callback<List<Photo>>() {
#Override
public void onResponse(Call<List<Photo>> call, Response<List<Photo>> response) {
}
#Override
public void onFailure(Call<List<Photo>> call, Throwable t) {
}
});
}
});
}
//Synchronous vs. Asynchronous
public interface ApiInterface {
#GET("?&method=flickr.photos.search&tags=<Ali>&api_key=1c448390199c03a6f2d436c40defd90e&format=json") //
Call<List<Photo>> getPhotos(#Query("q") String photoSearchTerm);
}
}
Try this out, this is a search API for Flickr
public static final String BASE_URL = "https://api.flickr.com/";
#GET("services/rest/?method=flickr.photos.search&api_key="+API_KEY+"&format=json&nojsoncallback=1&extras=url_m")
Call<FlickrModel> getImages(#Query("text") String query);