In android there is the AsyncTask which runs a thread and then i can use the method on post execute to interact with main thread again. is there an equivalent to this in java? i am trying to run a timer on separate thread (doInBackground) and once the time is finished it will then allow me to interact with the main theard to restart a service (onPostExecute will restart service)
I'm not Android developer but I think it could be easily implemented by using a CompletableFuture on Java 8:
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.CompletableFuture;
import javax.swing.SwingUtilities;
public abstract class AsyncTask <Params, Progress, Result> {
protected AsyncTask() {
}
protected abstract void onPreExecute();
protected abstract Result doInBackground(Params... params) ;
protected abstract void onProgressUpdate(Progress... progress) ;
protected abstract void onPostExecute(Result result) ;
final void publishProgress(Progress... values) {
SwingUtilities.invokeLater(() -> this.onProgressUpdate(values) );
}
final AsyncTask<Params, Progress, Result> execute(Params... params) {
// Invoke pre execute
try {
SwingUtilities.invokeAndWait( this::onPreExecute );
} catch (InvocationTargetException|InterruptedException e){
e.printStackTrace();
}
// Invoke doInBackground
CompletableFuture<Result> cf = CompletableFuture.supplyAsync( () -> doInBackground(params) );
// Invoke post execute
cf.thenAccept(this::onPostExecute);
return this;
}
}
Solution Tailored for You
In short, look at java: run a function after a specific number of seconds.
For your purpose, you don't need an AsyncTask. AsyncTask is for running something that needs the time, but you would prefer it didn't (e.g. a complex calculation or fetching data from the internet). It's for getting around the problem that you would need to wait.
What you want to do instead is to introduce a delay, or more precisely you want to schedule some action to happen after a delay. You can use a class like AsyncTask for this as well, but it's an overkill and results in more complicated code. You should instead use a class which is tailored for delayed execution, which is Timer and TimerTask:
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
// your code here
}
},
5000
);
Equivalent of AsyncTask in standard Java
Note that AsyncTask is connected to a UI concept (UI = user interface), because it may only be started from the UI thread. It's not for generally running something asynchronously.
Thus, the best matching equivalent of android's AsyncTask is SwingWorker in Java. Swing is Java's standard UI framework. It has a similar concept as android with a UI thread. In Swing, this thread is called the Event Dispatch Thread. Hence, the design of SwingWorker is also very similar to AsyncTask. Even the doInBackground() method has the same name in both classes.
Asynchronous Execution in General
If your requirement is not related to a UI and you only want to source some time consuming operation out so it executes asynchronously, then you need to look at executors. There is a variety of different ways to use executors for many different purposes, so this would go beyond the scope of this answer. If you are interested in further information, start with Jakob Jenkov's tutorial on ExecutorService.
Related
I want to update my UI from a Thread which updates a Progressbar. Unfortunately, when updating the progressbar's drawable from the "runnable" the progressbar disappears!
Changing the progressbars's drawable in onCreate() on the otherside works!
Any Suggestions?
public void onCreate(Bundle savedInstanceState) {
res = getResources();
super.onCreate(savedInstanceState);
setContentView(R.layout.gameone);
pB.setProgressDrawable(getResources().getDrawable(R.drawable.green)); //**Works**/
handler.postDelayed(runnable, 1);
}
private Runnable runnable = new Runnable() {
public void run() {
runOnUiThread(new Runnable() {
public void run()
{
//* The Complete ProgressBar does not appear**/
pB.setProgressDrawable(getResources().getDrawable(R.drawable.green));
}
});
}
}
You should do this with the help of AsyncTask (an intelligent backround thread) and ProgressDialog
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread. An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called begin, doInBackground, processProgress and end.
The 4 steps
When an asynchronous task is executed, the task goes through 4 steps:
onPreExecute(), invoked on the UI thread immediately after the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.
onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.
onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
Threading rules
There are a few threading rules that must be followed for this class to work properly:
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.)
Example code
What the adapter does in this example is not important, more important to understand that you need to use AsyncTask to display a dialog for the progress.
private class PrepareAdapter1 extends AsyncTask<Void,Void,ContactsListCursorAdapter > {
ProgressDialog dialog;
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(viewContacts.this);
dialog.setMessage(getString(R.string.please_wait_while_loading));
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
/* (non-Javadoc)
* #see android.os.AsyncTask#doInBackground(Params[])
*/
#Override
protected ContactsListCursorAdapter doInBackground(Void... params) {
cur1 = objItem.getContacts();
startManagingCursor(cur1);
adapter1 = new ContactsListCursorAdapter (viewContacts.this,
R.layout.contact_for_listitem, cur1, new String[] {}, new int[] {});
return adapter1;
}
protected void onPostExecute(ContactsListCursorAdapter result) {
list.setAdapter(result);
dialog.dismiss();
}
}
The most simplest solution I have seen to supply a short
execution to the UI thread is via the post() method of a view.
This is needed since UI methods are not re-entrant. The
method for this is:
package android.view;
public class View;
public boolean post(Runnable action);
The post() method corresponds to the SwingUtilities.invokeLater().
Unfortunately I didn't find something simple that corresponds to
the SwingUtilities.invokeAndWait(), but one can build the later
based on the former with a monitor and a flag.
So what you save by this is creating a handler. You simply need
to find your view and then post on it. You can find your view via
findViewById() if you tend to work with id-ed resources. The resulting
code is very simple:
/* inside your non-UI thread */
view.post(new Runnable() {
public void run() {
/* the desired UI update */
}
});
}
Note: Compared to SwingUtilities.invokeLater() the method
View.post() does return a boolean, indicating whether the
view has an associated event queue. Since I used the
invokeLater() resp. post() anyway only for fire and forget,
I did not check the result value. Basically you should
call post() only after onAttachedToWindow() has been called
on the view.
Best Regards
If you use Handler (I see you do and hopefully you created its instance on the UI thread), then don't use runOnUiThread() inside of your runnable. runOnUiThread() is used when you do smth from a non-UI thread, however Handler will already execute your runnable on UI thread.
Try to do smth like this:
private Handler mHandler = new Handler();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gameone);
res = getResources();
// pB.setProgressDrawable(getResources().getDrawable(R.drawable.green)); **//Works**
mHandler.postDelayed(runnable, 1);
}
private Runnable runnable = new Runnable() {
public void run() {
pB.setProgressDrawable(getResources().getDrawable(R.drawable.green));
pB.invalidate(); // maybe this will even not needed - try to comment out
}
};
Use the AsyncTask class (instead of Runnable). It has a method called onProgressUpdate which can affect the UI (it's invoked in the UI thread).
You need to create a Handler in the UI thread and then use it to post or send a message from your other thread to update the UI
If you don't like the AsyncTask you could use the observer pattern. In that example use the ResponseHandler as an inner class in your activity then have a string message that will set the progress bars percentage... You would need to make sure that any alterations to the UI are performed within the ResponseHandler to avoid freezing up the UI, then your worker thread (EventSource in the example) can perform the tasks required.
I would use the AsyncTask tho, however the observer pattern can be good for customization reasons, plus its easier to understand. Also im not sure if this way is widely accepted or will 100% work. Im downloading and the android plugin now to test it
As recommended by official documentation, you can use AsyncTask to handle work items shorter than 5ms in duration. If your task take more time, lookout for other alternatives.
HandlerThread is one alternative to Thread or AsyncTask. If you need to update UI from HandlerThread, post a message on UI Thread Looper and UI Thread Handler can handle UI updates.
Example code:
Android: Toast in a thread
I recently re-imported a perfectly fine android project into Android Studio and it has unilaterally decided to complain (and red under squiggle) code that is DEFINITELY safe.
I get this red squiggle in the IDE every time (but only in postExecute):
Method publishProgress must be called from the worker thread, currently inferred thread is main thread
private void triggerClick() {
final class LoginHttpTask
extends
AsyncTask<String/* Param */, Boolean /* Progress */, String /* Result */> {
#Override
protected String doInBackground(String... params) {
publishProgress(true);
}
#Override
protected void onPostExecute(String checkPhpResponse) {
publishProgress(false);
}
}
new LoginHttpTask.execute();
}
What is the cause and why does the code run perfectly fine anyway?
This is a linting issue. From the documentation for publishProgress(Params...) (my bold):
This method can be invoked from doInBackground(Params...) to publish updates on the UI thread while the background computation is still running.
So this method is designed to only be called on a background thread, and this is reflected in the source of the method with the #WorkerThread annotation:
#WorkerThread
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
So while doInBackground(String...) is run on a background thread, onPostExecute(String checkPhpResponse) is run on the UI thread as you're meant to update your UI directly within that callback. Because publishProgress(Params...) is annotated as #WorkerThread, the IDE throws up an error even though the code will compile - it works, but it's bad practice.
Without any further context as to how your AsyncTask is being used I can't advise as to how to update your code, but I would advise to avoid using publishProgress(boolean) and instead update your UI directly from within onPostExecute(String)
In my application , I have this logic when the user logins , it will call the below method , with all the symbols the user owns .
public void sendSymbol(String commaDelimitedSymbols) {
try {
// further logic
} catch (Throwable t) {
}
}
my question is that as this task of sending symbols can be completed slowly but must be completed , so is there anyway i can make this as a background task ??
Is this possible ??
please share your views .
Something like this is what you're looking for.
ExecutorService service = Executors.newFixedThreadPool(4);
service.submit(new Runnable() {
public void run() {
sendSymbol();
}
});
Create an executor service. This will keep a pool of threads for reuse. Much more efficient than creating a new Thread each time for each asynchronous method call.
If you need a higher degree of control over your ExecutorService, use ThreadPoolExecutor. As far as configuring this service, it will depend on your use case. How often are you calling this method? If very often, you probably want to keep one thread in the pool at all times at least. I wouldn't keep more than 4 or 8 at maximum.
As you are only calling sendSymbol once every half second, one thread should be plenty enough given sendSymbols is not an extremely time consuming routine. I would configure a fixed thread pool with 1 thread. You could even reuse this thread pool to submit other asynchronous tasks.
As long as you don't submit too many, it would be responsive when you call sendSymbol.
There is no really simple solution. Basically you need another thread which runs the method, but you also have to care about synchronization and thread-safety.
new Thread(new Runnable() {
public void run() {
sendSymbol(String commaDelimitedSymbols);
}
}).start();
Maybe a better way would be to use Executors
But you will need to case about thread-safety. This is not really a simple task.
It sure is possible. Threading is the way to go here. In Java, you can launch a new thread like this
Runnable backGroundRunnable = new Runnable() {
public void run(){
//Do something. Like call your function.
}};
Thread sampleThread = new Thread(backGroundRunnable);
sampleThread.start();
When you call start(), it launches a new thread. That thread will start running the run() function. When run() is complete, the thread terminates.
Be careful, if you are calling from a swing app, then you need to use SwingUtil instead. Google that up, sir.
Hope that works.
Sure, just use Java Threads, and join it to get the results (or other proper sync method, depends on your requirements)
You need to spawn a separate thread to perform this activity concurrently. Although this will not be a separate process, but you can keep performing other task while you complete sending symbols.
The following is an example of how to use threads. You simply subclass Runnable which contains your data and the code you want to run in the thread. Then you create a thread with that runnable object as the parameter. Calling start on the thread will run the Runnable object's run method.
public class MyRunnable implements Runnable {
private String commaDelimitedSymbols;
public MyRunnable(StringcommaDelimitedSymbols) {
this.commaDelimitedSymbols = commaDelimitedSymbols;
}
public void run() {
// Your code
}
}
public class Program {
public static void main(String args[]) {
MyRunnable myRunnable = new MyRunnable("...");
Thread t = new Thread(myRunnable)
t.start();
}
}
Because for some strange reasons, when I use AsyncTask to connect to a webpage, the UI of my app lags to almost the point of freezing while the AsyncTask is connecting to the webpage.
I thought this was because the connection usually takes quite long, at least 4 seconds.
I want to be able to update my TextView after my Thread have finished, but how do I do that in Android besides using AsyncTask?
There are a few methods to do that:
Use Threads or Runnables
Use Handlers, sending messages to its
Use RunOnUIThread method
Use the method (this is my favorite) post. It's not necessary to use a context/activity instance
For example, you can create a new Handler() and when you want to run code in the main thread do:
public static Handler interfaceHandler = new Handler();
...
mInterfaceHandler.post(new Runnable() {
#Override
public void run() {
//Your stuff
}
});
To complete the information, all Views in Android can make this post(Runnable) . This method add a runnable to their task to do, for that reason is recommendable not use views because the App will slow down. The static handler is perfect to make this work and is very easy to implement
Something like this should work
runOnUiThread(new Runnable() {
public void run() {
// do some stuff here
}
});
So I'm working on my "hello world" application in android/java, and elected to do a sports app (which is strange...I don't like sports...but whatever). So I set up my layout, allow users to 'drill down', so they can see the layout for Baseball, or MLB, or the Indians. Say a user selects 'Indians' from the MLB view. I update the tabs, potentially the color scheme, background, etc, and load the data for the 'news' and 'players' tabs (the latter of which is unique to team layouts). Unfortunately, api calls can sometimes take relatively long to complete, especially when the free API from ESPN is capped at 1 call per second. I do some significant caching already, but there's no way I can guarantee that I won't be loading both 'news' and 'players' for 'Indians' at the same time, so one of the requests will have to wait a full second to return.
So my solution is to have a data loading thread - the UI says 'get me this data', and does the UI work not contingent on the data being there. The question though is - once the data is returned from the data loader (as each piece comes back), how should it update or notify the UI appropriately? My current thought is:
UI thread:
OnSelectIndians()
{
DataLoadThread.GetIndiansPlayers();
DataLoadThread.GetIndiansNews();
// UI stuff
}
OnPlayersLoaded(Array Players)
{
if (layout == INDIANS_LAYOUT) // Make sure we haven't changed layouts
{
foreach player in Players
tab[PLAYERS].textview.text += player
}
}
But this isn't a problem I've had to deal with before. Is this the right way to go about it? Or is there a better/easier design I can use? I don't particularly like requiring the UI thread to have a 'on data returned' method for every type of data I can request. My other loosely-formed idea is to create a lambda function in the UI code, which is passed to the data loader and executed in the data loading thread, so:
DataLoadThread.Queue(
foreach player in GetIndiansPlayers()
myView.tab[PLAYERS].textview.text += player;
);
But I think this is probably the worse route, as now we have 2 threads interacting with the UI. Any advice?
Edit: Okay I got it working using AsyncTask. Out of the box, it still has the problem listed above that I would have to create a new derived class for every type if data I load (so PlayerLoadTask, NewsLoadTask, StandingsLoadTask, etc etc). I also wanted was to have most of the logic visible during the call, so if I'm looking at the event code I know what its doing. Below is the working implementation - would appreciate any feedback on it, but I'll accept the first answer below just the same.
abstract public class LoadDataHelper {
public LoadDataHelper(DataLoader dl, Object param) {
mDataLoader = dl;
mParam = param;
}
abstract public LinkedList<String> LoadData();
protected DataLoader mDataLoader;
protected Object mParam;
}
abstract public class UpdateUIHelper {
public UpdateUIHelper(MyActivity context) {
mContext = context;
}
abstract public void UpdateUI(LinkedList<String> results);
protected MyActivity mContext;
}
private class LoadDataTask extends AsyncTask<Void, Void, LinkedList<String> > {
private LoadDataHelper mLdh;
private UpdateUIHelper mUih;
LoadDataTask(LoadDataHelper ldh, UpdateUIHelper uih) {
mLdh = ldh;
mUih = uih;
}
#Override
protected LinkedList<String> doInBackground(Void... params) {
return mLdh.LoadData();
}
#Override
protected void onPostExecute(LinkedList<String> results) {
mUih.UpdateUI(results);
}
}
//
// .....
//
LoadDataTask task = new LoadDataTask(new LoadDataHelper(mDataLoader, "football") {
public LinkedList<String> LoadData() {
return mDataLoader.LoadLeaguesFromSport((String)mParam);
}
},
new UpdateUIHelper(this) {
public void UpdateUI(LinkedList<String> results) {
TextView tv = (TextView)findViewById(R.id.tv1);
tv.setText("");
for (String res : results) {
tv.append(res + "\n");
}
}
});
task.execute();
Take a look at:
1) AsyncTask
http://developer.android.com/reference/android/os/AsyncTask.html
The AsyncTask.onPostExecute will be executed in the UI thread.
I think this is the most common technique to do background processing.
2) runOnUIThread: If you are managing your own worker thread, you can use this in a worker thread to make sure code is run on the UI thread.
Its always better to have UI work in UI thread, and Non-UI work in Non-UI thread, But this became a Law from the arrival of HoneyComb in Android.
2 ways to do it in Android.
1. Use Java thread with Handler..
Create a thread to do the process heavy background task, and then display the data using
Handler...
2. Use AsyncTask<>, which is specially designed for Android, to sync the UI work and Non-UI
work. AsyncTask is also known as painless threading.
This is what AsyncTask was designed to do ,
Here is the tutorial that I learned from.
Here is what you do
Create a class that extends AsyncTask
Implement doInBackground and onPostUpdate methods
In the onPostUpdate method update the ui , you can use runOnUiThread to avoid any issues during ui update
The advantage of this using Async tasks is that you can even update the progress and display a visual indicator to the user , You can as easily cancel the task to stop the loading if required
AsyncTask is essentially a helper that simplifies the use of threads
Your best bet is to use the AsyncTask. I created a similar app that made 25+ calls to a server to download images. Using the AsyncTask will cut that time greatly, and still provide a great user experience. Here is a great tutorial on how to use/setup an AsyncTask:
http://www.peachpit.com/articles/article.aspx?p=1823692&seqNum=3
async task is the solution for you
here is a tutorial