Asynchronous task isn't being asynchronous - java

I'm developing a chat application in Android and have run into a massive problem. I need a thread to constantly run in the background (polling a server), and have attached it to my main process via a Handle.
The main problem is: As long as this background thread is running, the foreground one grinds to a complete halt!
Here is an incomplete chunk of code (because the full version is much longer/uglier)...
public class ChatActivity extends Activity {
...
private Thread chatUpdateTask;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
...
chatUpdateTask = new ChatUpdateTask(handler);
chatUpdateTask.start();
}
public void updateChat(JSONObject json) {
// ...
// Updates the chat display
}
// Define the Handler that receives messages from the thread and update the progress
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
// Get json from the sent Message and display it
updateChat(json);
}
};
public class ChatUpdateTask extends Thread {
Handler mHandler; // for handling things outside of the thread.
public ChatUpdateTask(Handler h) {
mHandler = h; // When creating, make sure we request one!
}//myTask
#Override
public void start() {
while(mState==STATE_RUNNING) {
// ...
// Send message to handler here
Thread.sleep(500); // pause on completion
}//wend
}//end start
/* sets the current state for the thread,
* used to stop the thread */
public void setState(int state) {
mState = state;
}//end setState
public JSONObject getChatMessages() {
// ... call server, return messages (could take up to 50 seconds to execute;
// server only returns messages when there are new ones
return json;
}
}//end class myTask
}

You're overriding start(). Threads run in their run() method.
http://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html

Related

Creating a callback on a class method

I'm struggling with a network connection class I've created. The result of the Runnable I create returns a JSON object that contains all the information needed from the server. The thread runs, and receives the data perfectly, but of course, the program keeps running in the meantime, which results in a JSONException as being NULL.
I created a class called NetworkManager, which has the following method (jsonResponse is initialized at the beginning of the class)
JSONObject jsonResponse;
public void createNetworkThread(Context context, final String requestURI, final RequestBody formParameters) {
Runnable runnable = new Runnable() {
#Override
public void run() {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(requestURI).post(formParameters).build();
Response response = null;
try {
response = client.newCall(request).execute();
String stringResponse = response.body().string();
NetworkManager.this.jsonResponse = new JSONObject(stringResponse);
// This works perfectly, "message" is received and printed to the log //
Log.d("Net", NetworkManager.this.jsonResponse.getString("message"));
} catch (IOException e) {
Log.d("Net", "Failed");
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
The above is called from the Activity, as:
Net.createNetworkThread(SignupActivity.this, requestURI, formVars);
JSONObject jsonResponse = Net.jsonResponse;
The JSON object jsonResponse is returning as NULL because the Thread is still accessing the server for the response.
I need to figure out how to stop the jsonResponse Object from being populated by Net.jsonResponse until the thread completes in order to stop it from returning NULL.
Any help?
I would only agree to the comments on your question and let you know, what you can do here.
If you are creating a thread just to get of the main UI thread to do the Network call you probably want to use OkHttp feature which allows you to get the Network call off the thread and provides you with callbacks to get the result something like this. you can check some example here
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
}
#Override
public void onResponse(Response response) throws IOException {
// this is the callback which tells you the network call was successful, If like to make some changes to UI, you should call `runOnUiThread`.
"YourClassName".this.runOnUiThread(new Runnable() {
#Override
public void run() {
}
});
}
});
or you can use AsyncTask which also gets your job done off the main UI thread and gives you the result in the callbacks.
private class MyTask extends AsyncTask<Void, Void, Void> {
//you can change the Type Void, Void, Void here to something which you want
//First Void belongs to doInBackground(Void... avoid)
//Second Void belongs to onProgressUpdate(Void... progress)
//Third Void belongs to onPostExecute(Void result)
// you may change these as you fit,
//when you want to start this class with your argument you can do something like this.
//new MyTask().execute("your argument to doInBackground");
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
// this is the method where you provide your implementation for doing a task off the main UI thread.
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// in this callback you are back in the main UI thread to make changes to UI depending on your response
}
}
here is an example of AsyncTask
If you want to offload the main thread, you should consider that the parallel task could finish it's execution after, generally speaking, any amount of time. Sure, you can wait in the main thread for the child thread to finish (using 'join()'), though this is kind of questionable in terms of speed gain.
Anyway, answering your question:
I need to figure out how to stop the jsonResponse Object from being
populated by Net.jsonResponse until the thread completes in order to
stop it from returning NULL.
I suggest you change
public void createNetworkThread(...
to
public Thread createNetworkThread(...
{
...
Thread thread = new Thread(runnable);
thread.start();
return thread;
}
And consequently
Thread t = Net.createNetworkThread(SignupActivity.this, requestURI, formVars);
t.join(); // Wait until 't' finishes -- try-catch is omitted for the sake of demo.
JSONObject jsonResponse = Net.jsonResponse;
This, apparently, opens question of performance, since main thread will be effectively completely blocked by 't.join()' until the child thread will finish.
Answering the question in the topic: in Java 8 you can use lambda functional interface like this:
package multithreaded;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Multithreaded {
public static void main(String[] args) throws Exception {
Logger logger = LoggerFactory.getLogger("Main");
Worker<String, String> worker = new Worker<String, String>(
(String s) ->
{ // This is actual call-back code.
// It will be called by method 'apply' of interface 'Function' in the 'Worker'.
// It will accept String parameter and pass it in this block as variable 's'
logger.info("Embrace the beauty and power of Java 8! "+s); // yes, we can use local variables of the parent thread.
return "Call-Back "+s;
}
);
logger.info("Application starts new Worker.");
worker.start();
logger.info("Worker is running in background.");
Thread.currentThread().sleep(500); // Simulate some activity here...
logger.info("Result is unpredictable (could be null): "+worker.getResult());
// Wait here until worker is fully finished
worker.join();
logger.info("Result is predictable: "+worker.getResult());
}
}
Worker.java:
package multithreaded;
import java.util.function.Function;
public class Worker<T extends String, R extends String> extends Thread {
private final Function<T, R> callBack;
private volatile R result;
public Worker(Function<T, R> callBack)
{ this.callBack = callBack; }
#Override
public void run()
{
try{
int i = (int)(Math.random()*1000);
// simulate some activity unpredictable in terms of duration
Thread.currentThread().sleep(i);
// After "activity" is finished -- call the call-back function and get result in local variable.
// (Synchronization ommited for the sake of simplicity)
result = this.callBack.apply((T)("Result "+i)); // now let's call the call-back function and save the result in local variable.
}
catch(InterruptedException e)
{e.printStackTrace();}
}
// Getter for the local variable, populated by call-back function.
// (Synchronization ommited for the sake of simplicity)
public R getResult()
{ return this.result; }
}
Running above code multiple times, you will notice that from the parent thread's perspective the result is still unpredictable until the child thread is completely finished.
P.s. I suggest you re-think entire logic of data processing in your app and consider re-factoring towards entirely independent multi-threaded processing (perhaps using producer-consumer logic).

Thread wait in Android

i have one problem with handling the thread in android ,in my class i have to create one thread which create some UI after that thread finish i will get some value ,here i want to wait my Main Process until the thread complete it process but when i put wait() or notify in Main process thread does not show the UI in my application
this is sample code
protected void onCreate(Bundle savedInstanceState) {
downloadThread = new MyThread(this);
downloadThread.start();
synchronized(this){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
String test=Recognition.gettemp();
public class MyThread extends Thread {
private Recognition recognition;
public MyThread(Recognition recognition) {
this.recognition = recognition;
// TODO Auto-generated constructor stub
}
#Override
public void run() {
synchronized(this)
{
handler.post(new MyRunnable());
}
notifyAll();
}
}
}
static public class MyRunnable implements Runnable {
public void run() {
settemp(template);
}
}
}
public static String gettemp() {
return template;
}
public static void settemp(String template) {
Recognition.template = template;
}
}
here i will not use AsynTask because i have some other issue that is reason i choose Thread even now the problem is Thread wait do any give the suggestion for this
- Use java.util.CountDownLatch , here you can let some process complete before kick-off some other code.
- countDown() and await() will be of use to you.......
See this example of CountDownLatch:
http://www.javamex.com/tutorials/threads/CountDownLatch.shtml
Use the logic below :-
new Thread(new Runnable()
{
#Override
public void run()
{
//do the code here such as sending request to server
runOnUiThread(new Runnable()
{
#Override
public void run()
{
//do here the code which interact with UI
}
});
}
}).start();
What do you expect to happen if you freeze the main UI thread?
You should be using an ASyncTask to show your gui in the onPreExecute method, do the task in doInBackground then display the result in the onPostExecute method.
As a plus you can update the progress using onProgressUpdate too.
This is not an solution just a advice on how should you structure you activity/app.
You should never block the main thread by calling wait() its a bad user experience and not advised. It would also case a Android Not Responding (ANR) popup.
You can have you thread updating the UI from the background and let the UI to be responsive. Load the static part of your UI in onCreate() and then fire up the background thread to lazy load rest of the component.

BlackBerry class equivalent to AsyncTask?

My requirement is to have a thread that maintains a socket connection between a BlackBerry device and a server and exchanges commands, similar to request and response.
My problem is that I need to have this thread running in the background all the time and keep the UI available to the user. So, when there is a command from the server, this thread parses it and updates the UI and also if there's an action from the BlackBerry user, it sends it to the server and the server in turn handles it.
I developed the same application in Android using AsyncTask and it's working well. But in BlackBerry, as there's no such class, I used the invokeLater() option. The communication works fine between the server and the BB device, but the UI is frozen on the BlackBerry.
Anyone have any idea how to get this right?
Vishal is on the right track, but a little more is needed to match Android's AsyncTask. Since enums and generics aren't available with Java 1.3 on BlackBerry, you can't match the Android API perfectly.
But, you could do something like this (not tested ... this is just a starting point for you):
import net.rim.device.api.ui.UiApplication;
public abstract class AsyncTask {
public static final int FINISHED = 0;
public static final int PENDING = 1;
public static final int RUNNING = 2;
private int _status = PENDING;
private boolean _cancelled = false;
private Thread _worker;
/** subclasses MUST implement this method */
public abstract Object doInBackground(Object[] params);
protected void onPreExecute() {
// default implementation does nothing
}
protected void onPostExecute(Object result) {
// default implementation does nothing
}
protected void onProgressUpdate(Object[] values) {
// default implementation does nothing
}
protected void onCancelled() {
// default implementation does nothing
}
protected void onCancelled(Object result) {
onCancelled();
}
public final int getStatus() {
return _status;
}
public final boolean isCancelled() {
return _cancelled;
}
public final boolean cancel(boolean mayInterruptIfRunning) {
if (_status == FINISHED || _cancelled) {
return false;
} else {
_cancelled = true;
if (mayInterruptIfRunning && _status == RUNNING) {
// NOTE: calling Thread.interrupt() usually doesn't work
// well, unless you don't care what state the background
// processing is left in. I'm not 100% sure that this is how
// Android's AsyncTask implements cancel(true), but I
// normally just cancel background tasks by letting the
// doInBackground() method check isCancelled() at multiple
// points in its processing.
_worker.interrupt();
}
return true;
}
}
protected final void publishProgress(final Object[] values) {
// call back onProgressUpdate on the UI thread
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
onProgressUpdate(values);
}
});
}
private void completeTask(final Object result) {
// transmit the result back to the UI thread
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
// TODO: not sure if status should be FINISHED before or after onPostExecute()
_status = FINISHED;
}
});
}
public AsyncTask execute(final Object[] params) throws IllegalStateException {
if (getStatus() != PENDING) {
throw new IllegalStateException("An AsyncTask can only be executed once!");
} else {
try {
onPreExecute();
_worker = new Thread(new Runnable() {
public void run() {
try {
// run background work on this worker thread
final Object result = doInBackground(params);
completeTask(result);
} catch (Exception e) {
// I believe if Thread.interrupt() is called, we'll arrive here
completeTask(null);
}
}
});
_status = RUNNING;
_worker.start();
} catch (Exception e) {
// TODO: handle this exception
}
}
return this;
}
}
Also, it's important to keep in mind the Threading Rules for Android's AsyncTask, which apply to the above implementation, too:
Threading rules
There are a few threading rules that must be followed
for this class to work properly:
The AsyncTask class must be loaded on the UI thread. This is done
automatically as of JELLY_BEAN.
The task instance must be created on
the UI thread.
execute(Params...) must be invoked on the UI thread.
Do not call onPreExecute(), onPostExecute(Result),
doInBackground(Params...), onProgressUpdate(Progress...) manually.
The task can be executed only once (an exception will be thrown if a
second execution is attempted.)
You can create a Class that extends my implementation of class AsyncTask. Good Luck :)
Here the methods onPreExecute, onPostExecute are executed on UI thread and doInBackground is called on worker thread. Since onPreExecute, onPostExecute are abstract you can override them and provide your implementation like showing and dismissing progress dialog.
The sequence in which methods get's executed is
1) onPreExecute
2) doInBackground
3) onPostExecute
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;
public abstract class AsyncTask {
Runnable runnable;
Thread threadToRun;
public abstract void onPreExecute();
public abstract void onPostExecute();
public abstract void doInBackground();
public void execute() {
try {
runnable = new Runnable() {
public void run() {
// TODO Auto-generated method stub
UiApplication.getUiApplication().invokeLater(
new Runnable() {
public void run() {
// TODO Auto-generated method stub
onPreExecute();
}
});
doInBackground();
UiApplication.getUiApplication().invokeLater(
new Runnable() {
public void run() {
// TODO Auto-generated method stub
onPostExecute();
}
});
}
};
threadToRun = new Thread(runnable);
threadToRun.start();
} catch (Exception e) {
// TODO: handle exception
Dialog.alert("Async Error Occured. " + e.toString());
}
}
}

General purpose network manager in Android

I'm working on an Android project (API level 10) which needs to send and receive http messages to/from a server.
I implemented a class named NetworkManager which provides different methods, one for each http request (e.g.: loginRequest(user pass), RegistrationRequest(user.....) ).
All these methods generates a JSON object that is passed to the method called sendMessage, which is the method that actually establish the connection, sends and receives the response (also a json object).
Of course network calls are time consuming, so i first decided to use an AsyncTask to display a progressDialog while the network operation is being performed.
The problem is that i need to get the response value retrived from the background thread before executing any other operation which involves the result itself done by the Main thread.
At the same time i would like to make a common and reusable implementation of the AsyncTask.
E.g.: I have a login activity which shows 2 EditText (username, password) and a button called Login. When I press the login button, a progressDialog must appear, and must be disposed once the doInBackground task is accomplished. Of course i could do this way:
onClick(View v) //called when the login button is pressed
{
onPreExecute()
{
//Show the progress dialog
}
doInBackground()
{
//Retreive the login response (an integer containing a message code) using sendLoginRequest(username, password);
//return the response
}
onPostExecute(int response)
{
//Dispose the progress dialog, then loginSucessfull ? start new activity : show error toast
}
}
But, doing this way i should implement an async task for every request i need to send which is what i would like to avoid because if i have N requests i should create N classes that extend AsyncTask.
Thank you!
What i would suggest you is to use INTERFACES for handling response of http request.
The background thread either it be a AysncTask or it be Thread needs to handle both
response
exception
Think it like this way
MainThread - Hey Background Thread do this operation and let me know when you are done.
MainThread - Ok till Background Thread executes its operation let me show progress dialog.
BackGroundThread - I am done with my work. hey MainThread here catch you response or exception
MainThread - Let me stop showing progress bar.
So we need to simulate this callback mechanism via code and also needs to take care that we implement a reusable architecture.
Something like this
Define a Interface
public interface HttpRequestResponse {
public void onSuccess(HttpResponse response);
public void onException(Exception exception);
}
class HttpRequestResponseHandler {
private ActionItem action;
private HttpRequestResponse hrr;
private Executor executor;
public enum ActionItem {
LOGIN_REQUEST ,
REGISTRATION_REQUEST
}
public HttpRequestResponseHandler(ActionItem action, HttpRequestResponse hrr) {
this.action = action;
this.hrr = hrr;
}
public void execute(){
executor = new Executor();
executor.execute();
}
private class Executor extends AsyncTask<Void,Void,Void> {
#Override
public Void doInBackground() {
switch(action) {
case LOGIN_REQUEST : doLogin();
break;
case REGISTRATION_REQUEST : doRegistration();
break;
}
}
}
private void doLogin() {
HttpResponse response = null;
Exception exception = null;
try {
response = makeHttpRequestHere();
} catch (Exception e) {
exception = e;
}
if(exception != null) {
hrr.onException(exception);
} else {
hrr.onSuccess(response);
}
}
}
Now in somewhere in your activity code file do like this.
HttpRequestResponse hrr = new HttpRequestResponse(){
#Override
public void onSuccess(HttpResponse response) {
hideProgressDialog();
handleResponse(response);
}
#Override
public void onException(Exception exception) {
hideProgressDialog();
showErrorDialog(exception.getMessage());
}
}
HttpRequestResponseHandler hrrh = new HttpRequestResponseHandler(ActionItem.LOGIN_REQUEST,hrr);
hrrh.execute();
showProgressDialog();
Hope all this lead to what you want.
Its been a long answer and took quite a effort of mine to figure. :)
why not just using AsyncTask.THREAD_POOL_EXECUTOR(Runnable run);
It wraps a thread pool based executor of #cores + 1 parallelity level.
Then you can simply invoke:
AsyncTask.THREAD_POOL_EXECUTOR(new Runnable(){
public void run(){
doLogin();
});

How do I ensure another Thread's Handler is not null before calling it?

My program threw a NullPointerException the other day when it tried to use a Handler created on another thread to send that thread a message. The Handler created by the other thread was not yet created, or not yet visible to the calling thread, despite the calling thread having already called start on the other thread. This only happens very rarely. Almost every test run does not get the exception.
I was wondering what the best way is to avoid this problem for sure with minimal complication and performance penalty. The program is a game and very performance sensitive, especially once it is running. Therefore I try to avoid using synchronization after setup, for example, and would prefer to avoid spinning on a variable at any time.
Background:
In Android the Handler class may be used to "enqueue an action to be performed on a different thread than your own". Documentation here:
http://developer.android.com/intl/de/reference/android/os/Handler.html
The Handler must be created on the thread where it will be used. So creating it in the constructor of a thread, which is run by the thread creating that thread, is not an option.
When the Handler is for a thread other than the UI thread, the Looper class must also be used:
http://developer.android.com/intl/de/reference/android/os/Looper.html
The documentation gives this example of using the two classes for this purpose:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
My very ugly workaround currently looks like this:
public class LooperThread extends Thread {
public volatile Handler mHandler;
public final ArrayBlockingQueue<Object> setupComplete = new ArrayBlockingQueue<Object>(1);
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
setupComplete();
Looper.loop();
}
public void waitForSetupComplete() {
while ( true ) {
try {
setupComplete.take();
return;
} catch (InterruptedException e) {
//Ignore and try again.
}
}
}
private void setupComplete() {
while( true ) {
try {
setupComplete.put(new Object());
return;
} catch (InterruptedException e) {
//Ignore and try again.
}
}
}
}
With the code in the creating thread looking like this:
LooperThread otherThread = new LooperThread();
otherThread.start();
otherThread.waitForSetupComplete();
otherThread.mHandler.sendEmptyMessage(0);
Are there any better solutions? Thanks.
I'd go with the classic wait/notify
public class LooperThread extends Thread {
private Handler mHandler;
public void run() {
Looper.prepare();
synchronized (this) {
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
notifyAll();
}
Looper.loop();
}
public synchronized Handler getHandler() {
while (mHandler == null) {
try {
wait();
} catch (InterruptedException e) {
//Ignore and try again.
}
}
return mHandler;
}
}
Handler returned from getHandler can then be used many times without invoking synchronized getHandler.
Preparing a Looper can block for a while, so I imagine you're hitting a condition where prepare() takes a moment to complete, thus mHandler is still undefined.
You could have your Thread extend HandlerThread, though even then you still have to wait to ensure the Looper has initialised. Perhaps something like this might work, where you have the Handler defined separately, but utilising the Looper of your custom thread.
Maybe.
private void setUp() {
mHandlerThread = new CustomThread("foo", Process.THREAD_PRIORITY_BACKGROUND);
mHandlerThread.start();
// Create our handler; this will block until looper is initialised
mHandler = new CustomHandler(mHandlerThread.getLooper());
// mHandler is now ready to use
}
private class CustomThread extends HandlerThread {
public void run() {
// ...
}
}
private class CustomHandler extends Handler {
CustomHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
// ...
}
}
I just want to add that the checked answer is the best one but if you test it like that is not going to work becouse you need to call super on run methode since it's in charge of preparing the looper so the code should be like this:
private void setUp() {
mHandlerThread = new CustomThread("foo", Process.THREAD_PRIORITY_BACKGROUND);
mHandlerThread.start();
// Create our handler; this will block until looper is initialised
mHandler = new CustomHandler(mHandlerThread.getLooper());
// mHandler is now ready to use
}
private class CustomThread extends HandlerThread {
public void run() {
super.run() // <- VERY IMPORTANT OTHERWISE IT DOES NOT WORK
// your code goes here
}
}
private class CustomHandler extends Handler {
CustomHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
// ...
}
}

Categories

Resources