I want to load some data on application startup that will be used by all activities.
I do this in the application's onCreate method and because I want this data to be downloaded before any activity is shown, I try to make a synchronous request using RequestFuture. However the TimeoutException is always thrown.
public void onCreate() {
super.onCreate();
appRequestQueue = Volley.newRequestQueue(this);
RequestFuture<JSONArray> requestFuture = RequestFuture.newFuture();
JsonArrayRequest request = new JsonArrayRequest(
URL,
requestFuture,
requestFuture);
appRequestQueue.add(request);
try {
JSONArray jsonArray = requestFuture.get(90, TimeUnit.SECONDS);
// Do processing. Never gets here
Log.v("*******************", "Application initialized");
} catch (JSONException je) {
} catch (InterruptedException ie) {
} catch (ExecutionException ee) {
} catch (TimeoutException te) {
// Always times out
Log.v("$$$$$$$$$$$$$$$$$$$$$$$$$", "It has timed out...");
}
What is the best way to get app-wide data keeping in mind that there is no one activity that is started first?
Yeah, according to the default behavior of the volley, the wake up notification (the delivery of the response) of the Request is posted on the Handler of the main UI thread.
So when the UI thread is blocked, the wake up notification will never be executed (also the response will never be delivered), and you'll always get a timeout.
I ran into this recently, the solution is to NOT make requests or handle them from the main thread ( UI ), it always throws a TimeoutException . Consider creating a AsyncTask and performing this request from there.
You can communicate with the MainActivity using the onPostExecute callback.
https://developer.android.com/reference/android/os/AsyncTask.html
Related
Wondering if its possible to monitor constantly some wifi connection to a server (some ip and port) and display the status of the connection, that is if the server is accessible/responsive or not.
By displaying the status i mean updating some textview displaying either "server up" or "server down".
(something similar to the wifi icon next to the battery indication at the top right..)
the answer is to make a thread class, which will constantly call (with a while loop) an asynctask. The asynctask will (try to) connect to the mysql server. the connection will be successful or not and accordingly a textview or something will be updated in the UIthread (using runOnUiThread)
an example of the code for the thread:
class servlookthread extends Thread {
#Override
public void run() {
while (keeplookingserver){
lookforserver lserv = new lookforserver(); // this is the asynctask thread
try {lserv.execute().get();} catch (ExecutionException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();} //! .get() it waits until the asynctask finishes
try {Thread.sleep(4000);} catch (InterruptedException e) {e.printStackTrace();} // some delay, 4 seconds
}
return;
}
}
the keeplookingserver is a boolean, "global" variable used to control the execution of the thread.
hope this helps someone! although i think its not elegant, its working for me
I define how to handle the response I receive from my server in an anonymous inner class, where I store the response in a Map to enable access from outside that inner class.
Since my server call is asynchronous, I implemented a while-loop to wait for the result to be put into the map, before return it to the calling function.
However, somehow my loop isn't executed (as far as I can tell at least), and the loop appear to block my request from ever being finished, which obviously leads to un endless loop.
public Login getLoginByUsername(String username)
{
long callID = counter.incrementAndGet();
System.out.println("Start call");
ServerConnection.get("myURI",null, new JsonHttpResponseHandler(){
#Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response){
try {
System.out.println("Call success, enter result:");
callResults.put(callID, new CallResult(Login.parseFromJson(response)));
System.out.println(callResults.get(callID));
} catch (JSONException e) {
e.printStackTrace();
}
}
});
System.out.println("start waiting");
while(callResults.get(callID) == null){
//wait
System.out.print(".");
}
System.out.println("\nwaiting over, return result:");
System.out.println(callResults.get(callID));
return (Login) callResults.remove(callID).content;
}
I'm sure that the request works just fine. If I remove the loop (and return null to avoid the NPE from accessing the not yet finished result), I can see from the console outputs that the request is performed and yiels a valid result after the function terminates.
I also tried to move the whole request (ServerConnection.get) to another method in case the method performing the asynchronous call must for some reason terminate for the call to be performed. This didn't help either.
Also, I never get the console output defined within the loop, so I doubt it's even executed properly...
What is happening here, and how can I fix it?
The while loop will probably max out your CPU and throttle all other execution. In such waiting loops you should always introduce some kind of delay, even 100-10ms is enough.
Just call Thread.sleep(100); in your loop (and handle the InterruptedException somewhere).
So for example:
while(callResults.get(callID) == null){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
return null; // Return null or just throw a RuntimeException. You can be pretty sure that this will never be called unless your app gets closed or your thread intentionally interrupted.
}
System.out.print(".");
}
Upon updating the code due to the related issue/question (How to return response to calling function? (Android-App calling Java REST-Server via JSON) if you're curious), I put a thread around my request:
public Login getLoginByUsername(String username)
{
long callID = counter.incrementAndGet();
new Thread(new Runnable() {
#Override
public void run() {
ServerConnection.get("person-login-relations?byUsername="+username,null, new JsonHttpResponseHandler(){
#Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response){
try {
callResults.put(callID, new CallResult(Login.parseFromJson(response)));
System.out.println(callResults.get(callID));
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
}) .start();
while(callResults.get(callID) == null){
//wait
}
return (Login) callResults.remove(callID).content;
}
This seems to have solved the problem I decribed here of the loop blocking the request. I guess this may be because the request or the response-handling might have been handled by the same thread that contained the loop and thus was waiting for the loop to finish. I'm not entirely sure though, especiall since I was using async requests before, which have been handled in a thread outside my control
i'm trying to achieve the following: do a single synchronous http request using Volley's Futures in a background thread, and have the current thread wait for the background thread to finish, so it can later handle the http response.
What actually happens is that after the .join(), everything seems to hang and I never enter the breakpoints inside the runnable's run method or get through to any command after the join().
NOTE - the current thread is an activity class, and this specific function is of a Java class whose services are called by the activity. I am aware that .join() on a UI thread causes it to hang...but only until the background thread is finished, right? Well, when I use .wait() instead of .join(), the background thread finishes really fast. It's almost as if calling join doesn't let the background thread do it's job.
private String requestConversionRatesFromApi() throws InterruptedException
{
final JSONObject[] localResponse = {null};
Runnable runnable = new Runnable()
{
#Override
public void run()
{
String url = "myurl";
RequestQueue queue = Volley.newRequestQueue(_context);
RequestFuture<JSONObject> future = RequestFuture.newFuture();
JsonObjectRequest request = new JsonObjectRequest(url, new JSONObject(), future, future);
queue.add(request);
try {
JSONObject jsonObject = future.get();
localResponse[0] = jsonObject; //doesn't get here either unless I'm using .wait() and then it happens really fast
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
};
Thread t = new Thread(runnable);
t.start();
t.join();
return "foo"; //Doesn't get here
}
I am trying to get the server time from pubnub with the time method
mPubnub.time(callback);
I suppose it is an asynchronous call then I have a waiting loop just after so I can wait for the result
time = -1;
mPubnub.time(callback);
while(time == -1);
In the call back I have
Callback callback = new Callback() {
public void successCallback(String channel, Object response) {
try {
JSONArray jsonArray = new JSONArray(response.toString());
time = jsonArray.getLong(0) / 10000;
return;
} catch (JSONException e) {
e.printStackTrace();
}
time = 0;
}
public void errorCallback(String channel, PubnubError error) {
Log.wtf("error/" + channel, error.toString());
time = 0;
}
};
All these calls are from doInBackground of an AsyncTask. Why is it blocking my ui thread. Also calls to publish are also blocking my UI thread and I only call them from an AsyncTask
Many people say the while loop blocks the UI thread but I don't understand why that loop in an AsyncTask would block the UI thread. It wasn't in the onPostExecute or onProgressExecute. It was in doInBackground and it shouldn't block the UI.
On the other hand removing the loop still blocks the UI thread
mPubnub.time(callback);
mPubnub.publish(channel, message, true, callback);
these simple calls block the UI thread and the application stops responding.
This is blocking your UI thread:
while(time == -1);
Instead of doing that, you should handle the success/failure via the callback. If the pubnub API takes a callback like this, it would appear as though it is already handling doing it on a background thread. Just take the appropriate action inside the callback handlers.
while(time == -1);
This line blocks your UI Thread, because of this pointer will never updated by other thread, it's not a volatile variable.
You can use Debug Bottle to detect UI Block codes in your project.
I am looking for some advise about the following, I have a HttpUtil class (util) in which I have my sendGetRequest- and sendPostRequest methods.
I use them to perform a successfull login to a website from which I am going to fetch some data.
Now, I call these methods in my MainActivity in a Asynctask:
protected Boolean doInBackground(Void... params) {
try {
//1. GET request
util.sendGetRequest(loginURL, null);
//2. Post request
util.sendPostRequest(loginURL, null);
//3. Final GET request
util.sendGetRequest(resultURL, null);
// Read stream
String[] response = util.readMultipleLinesRespone();
for (String line : response) {
System.out.println(line);
}
} catch (InterruptedException e) {
return false;
} catch (Exception e) {
e.printStackTrace();
}
}
I am looking for a solution so that one waits for another to finish (1st get then post, finally get), if it`s possible I want to keep this util.class intact and not put everything in the Asynctask (doInBackground).
Is this possible or do I have the wrong approach?
Your opinions and advise please.
Thank you in advance.
The approach I normally use is this:
First, consider using an Event for instance a library like this that will not only decouple your code but also make it so easy to notify your activity when the first HttpGet request is completed.
Next, start your GET request inside doInBackground and then notify your activity once the process is completed - normally inside onPostExecute
When in your activity, assuming you use the EventBus library, you can execute the next AsyncTask which will do your next task like doing a POST request accordingly.
Using this approach should really make your life easier - specifically helps you know when something is completed and so you can proceed with the next task as needed.
Good luck!
You can have two AsyncTasks. One for get and other for post. First execute get request. Then in onPostExecute of the first AsyncTask execute the second AsyncTask that sends the post request in doInBackground();
Your HttpUtil class should somehow signal that the response is received.
For example, put this code in HttpUtil to signal end of operation:
synchronized (this) {
done = true;
notifyAll();
}
and this code will wait for the operation to end:
while(!util.isDone()) {
try {
synchronized(util) { util.wait(); }
} catch(Exception e) { ... }
}