Android - How to reload data after Volley request - java

My question is simple. I have a simple fragment which is not a list but simply 5 TextViews. Once this fragment runs, it fires a volley request to an API endpoint where its response arrives after the onCreateView method has already finished. Normally, one would use adapter.notifyDataSetChanged() so that the new data could be shown even if it arrives after the normal fragment lifecycles have ended. The problem is that since my fragment is not a list, it does not have an adapter. How could I use notifyDataSetChanged() in the absence of an adapter? What solution should I be looking for to solve this problem? Any feedback would be greatly appreciated.

Assuming you have a field of
private TextView textView1;
And somewhere you have a StringRequest for Volley, then in the onResponse for the Response.Listener, just set the text of the TextView.
public void onResponse(String response) {
textView1.setText(response);
}
If you have a seprate class that does your Volley requests, then you should add a parameter for Response.Listener to your method.
For example
MyServer.doLogin("http://myurl.com/login", "username:password", new Response<String>.Listener() {
public void onResponse(String response) {
// Do something here
}
};
Where MyServer.doLogin could be something like this (note: this is an example, it may not compile)
public void doLogin(String url, String cred, Response<String>.Listener callback) {
StringRequest request = new StringRequest(
url,
Request.GET,
callback,
new Response.ErrorListener() { ... }
);
addToRequestQueue(request);
}

You may try to reset the data collection and use Invalidate()to refresh the view ,try to mix these operations in a method and call them when you need.

Related

How to properly write a volley callback

I am trying to write a volley get a request to fetch me all the users of my API. I have successfully done this, however, my function has stopped working. If I run my code now and attempt to fetch all the users, it will just return an empty array. If I try to fetch them one more time without stopping the run, it will return to me all of the users.
This is my function:
public ArrayList<User> getAllUsers(final VolleyCallBack callBack) {
requestQueue = Volley.newRequestQueue(this);
JsonArrayRequest arrayRequest = new JsonArrayRequest(
Request.Method.GET,
"http://ecoproduce.eu/api/User",
null,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.e("Rest response", response.toString());
Gson gson = new Gson();
User user = new User();
for (int i = 0; i < response.length(); i++) {
try {
user = gson.fromJson(response.getJSONObject(i).toString(), User.class);
} catch (JSONException e) {
e.printStackTrace();
}
allUsers.add(user);
}
callBack.onSuccess();
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Error response", error.toString());
}
}
);
requestQueue.add(arrayRequest);
return allUsers;
}
This is my callback interface:
public interface VolleyCallBack {
ArrayList<User> onSuccess();
}
This is how I call the function:
ArrayList<User> currentUsers;
currentUsers = getAllUsers(new VolleyCallBack() {
#Override
public ArrayList<User> onSuccess() {
Log.e("Bla", "ALL DONE!!!");
return allUsers;
}
});
I don't know what the problem is, this was working perfectly like an hour ago but for some reason, it has stopped. This is my first attempt at writing RESTful requests and I can't really pinpoint the error of my code.
SOLUTION:
Problem solved by making the changes suggested by Reaz Murshed and moving the getAllUsers call to the body of onCreate insted of it being within the onClick() function.
The getAllUsers function is returning allUsers immediately after putting a get request in a background thread. That being said, you are getting the user list when the background thread for your API was not finished fetching your user list and hence you are getting an empty list for the first time.
However, during the second time, you are having it, because the first API request fetched the users successfully and updated your allUsers list. So, actually you are not getting the user list from the second time API request, you are getting it from the request that was made previously.
To tackle this problem, do not return the allUsers from your getAllUsers function immediately after sending the API request. Wait for the API request to fetch the data for you and you already have a setup for success callback, where you should be able to get your desired user data.
Hence, you need to implement your onSuccess method in your Activity or Fragment or wherever you are calling the getAllUsers method, and perform necessary actions with the list of users on receiving a successful callback.
I would suggest modifying your callback function a little so that you can actually pass on the information that you fetched from the server.
public interface VolleyCallBack {
void onSuccess(ArrayList<User>);
}
And in the onResponse function of Volley callback, pass the user list that was fetched as follows.
callBack.onSuccess(allUsers);
I hope that helps!

How to form an URL in Background thread before using it with an API?

I am working with an API for the first time.
My need is that I need to form an URL with certain parameters out of which one parameter cannot be formed in the Main UI thread and has to be formed in the Background thread.
I am planning to use to volley library to post the GET request.
I am using the Needle library which helps in running background tasks. This is What I have tried till now.
Needle.onBackgroundThread().execute(new UiRelatedTask<String>() {
#Override
protected String doWork() {
return url = GetUrl();
}
#Override
protected void thenDoUiRelatedWork(String result1) {
Log.e("JSON", url);
final JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener() {
#Override
public void onResponse(Object response) {
Log.e("JSON", response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("JSON", error.toString());
}
});
RequestQueue queue = VolleyController.getInstance(Activity.this.getApplicationContext()).getRequestQueue();
queue.start();
queue.add(jsonObjectRequest);
}
});
But the Main problem is that After the GetUrl() method immediately the thenDoUiRelatedWork method is called hence the request is made using an Invalid URL as the URL will still be loading in the background and then when the loading of the URL is over I am logging the URL Which is right.
I cannot use an AysncTask as my app is already using three AsyncTaks and additionally two more could be activated by the user based on the feature he is using. And also the API request has to be done in various places (3-4 places) hence using an AsyncTask will not be suitable.
Can anyone help me to first form the URL fully in the Background and the use volley to post the GET request.

Create a Custom Completion/Callback Handler to return Objects after a HTTP Request is Completed

I am an iOS Developer starting to learn Android. In Swift, creating a completion handler is very simple, but I still can't find a way to do it in Java.
I am sorry if this question is too noob for StackOverflow people.
Problem
I am creating a class to handle all my Http Request which is done using Retrofit.
I make this function is my RequestHelper.java
public static void checkEmailAvailability(String email) {
MyWebServiceAPI serviceAPI = retrofit.create(MyWebServiceAPI.class);
Call<APIResults> call = serviceAPI.checkEmailAvailability(getAuthenticationHeader(), RequestBody.create(MediaType.parse("text/plain"), email));
call.enqueue(new Callback<APIResults>() {
#Override
public void onResponse(retrofit.Response<APIResults> response, Retrofit retrofit) {
//Parse Response Json
//Get some value and place it inside an object
//ANDI WOULD LIKE RETURN SOME BOOLEAN VALUE AND SOME OTHER STRING
}
#Override
public void onFailure(Throwable t) {
//I WOULD LIKE A BOOLEAN VALUE HERE
}
});
}
I call it like this from my MainActivity
RequestHelper.checkEmailAvailability("user#user.com");
Now the function is still void but I would like for it to return something after the on the onResponse and onFailure method.
Any thoughts please?
You should pass the Callback object as a parameter to the checkEmailAvailability().
And implement the interface when you call the method from your MainActivity,and use the response parameter in the onXXX() method as the data returned to update UI.

Java: Wait with main thread for response listener in extra method

So, I'm writing an android app. During OnCreate() of an activity, I request some JSONObjects via HTTP GET. That method has a response listener that, well, does something when it gets a JSONObject. In the OnCreate-method, I need to use the response, so can I somehow set it up so that the OnCreate method waits until the response listener does it's job?
Do I have to use multithreading? Here's the code I'm talking about:
Here's the call in OnCreate():
...
// Instantiate the RequestQueue.
final RequestQueue queue = Volley.newRequestQueue(this);
executeJson(QUERY_URL);
System.out.println(jsonresponse);
...
Here's the called method:
private void executeJson(String url) {
SharedPreferences prefs = this.getSharedPreferences("AppPref", MODE_PRIVATE);
final String token = prefs.getString("token", null);
RequestQueue queue = Volley.newRequestQueue(this);
Map<String, String> params = new HashMap<String, String>();
System.out.println(token);
params.put("access_token", token);
CustomRequest jsonRequest = new CustomRequest(url, params,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
jsonresponse = response;
}
}, this.createRequestErrorListener());
System.out.println(jsonRequest);
queue.add(jsonRequest);
}
I realize that a simple Thread.Sleep() would, well, make my app go to sleep entirely, so that can't be the solution.
The intention of this activity is to be a "Loading Activity" - It pops up once the user wants to access his data and creates an intent to the data activity, destroying itself after the data is loaded.
Yes, you need to do the request in a background thread. Use an AsyncTask, or other method. You do not want to do an arbitrarily long running request on the UI thread, nor 'pause' the UI thread to wait for the request to return. Read Android Processes and Threads for more info using threads in Android.

Android program logic flow of using callbacks

I am working on an Android App, in which I need to make a lot of http queries. Since Android has a constrain to prevent program making http request on UI thread, I have to use a lot of Async methods to get response from the server. I am not a guru of using callbacks, there's a code design problem I am facing now:
Basically, I have a activity to display. I want the app to make a HttpRequest to server when the activity is created, so I can prepare the content of the activity based on the query response.
Since I am using the Google Volley library to make http requests, my code design is:
// in the Activity
OnCreate(Bundle b){
String response = RequestManager.makeRequest(args);
// other works based on the response in this activity.
}
// RequestManager Class
public static String makeRequest(args){
String url = getUrl();
// response callback
Response.Listener<String> responseListener = new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// Don't know what to do here
}
};
// error callback
Response.ErrorListener errorListener = new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// deal with errors
}
};
BuildRequestAndPushToQueue(url, responseListener, errorListener);
// No way to return the response!
}
I know my design is totally incorrect, because String response = RequestManager.makeRequest(args); is intent to wait for a blocking call, but the call is actually async.
My ultimate goal is to let the response String returned to some code in the activity, so it can use the activity context to do the rest works (like access to a imageview, etc). But I am not sure how to design the code flow to make this happen.

Categories

Resources