I have the following void:
public void load() {
//loading big picture from the Internet
}
And i want it to run in a new Thread.
I can call this procedure like this:
new Thread(new Runnable() {
public void run() {
load();
}
}).start();
or it would be better to modify this void:
public void load() {
new Thread(new Runnable() {
public void run() {
//loading big picture from the Internet
}
}).start();
}
and simply call it:
load();
Or there is no different?
Functionally, they are identical. There are designed details that might make you consider the first way over the other.
You may want the first option if you had a lot of different threads that didn't their own individual things but also called load(). In that case, you already had created the thread, so if they called load() you wouldn't want/need to create another.
The second option is very convenient. You can simply call load() wherever you want. If, in the future, the load() method changes to a point where it's not blocking, then you can change it and no further code changes would be needed.
Alternatively, consider using AsyncTask for this as previously suggested. It was specifically built for exactly what you're trying to do.
Related
My question seems very simple but i can't seem to the logic right.
Am trying to run methods from other classes using the UI thread. I could do this this simply by wrapping my methods like this
runOnUiThread(new Runnable() {
public void run() {
Log.d("UI thread", "I am the UI thread");
ui.myMethod("changetext");
}
});
but my goal is to have a class that wraps methods to be run on the UI thread as having runOnUiThread() almost 5 times in a single class seems very untidy. Any pointers?
If you're calling the same UI method repeatedly, you could streamline the client code by creating the Runnable in a method:
private void updateUi(final String message) {
runOnUiThread(new Runnable() {
public void run() {
ui.myMethod(message);
}
});
}
Then your client code would simply call updateUi("changetext"). (This code assumes that ui is final. If not, you could pass in a final reference.)
If you're calling a different UI method every time, this doesn't gain you anything as you'd need a separate update method for each UI method. Your existing code is as elegant as it gets.
If you really have to do this from multiple classes, you could create a public static method that will run a runnable on the main thread. Something like this:
public class Util {
public static void runOnUI(Activity a, Runnable r){
a.runOnUIThread(r);
}
}
You call it by doing something like this:
Util.runOnUI(getActivity(), mRunnable);
I've been writing android apps for some months now, and I'm at the point where I'm building an actual needed app.
As I want that to work nice and fast, I made a Workerthread to do all kinds of tasks in the background while the UI can...build up and work and stuff.
It's based on the Android Studio Drawer app blueprint.
In Main.onCreate I got my operator=new Operator(), which extends Thread.
Now, when loading a new Fragment, it sometimes calls MainActivity.operator.someMethod() (I made operator static so I can use it from anywhere), and after some time I realized, the only tasks actually running in background are those in the operators run() method and an Asynctask my login Fragment runs. Everything else the UI waits for to complete and therefore gets executed by the UI thread.
So I thought: no problem! My operator gets a handler which is built in run(), and I change those tasks:
public void run() {
Looper.prepare(); //Android crashed and said I had to call this
OpHandler = new Handler();
LoadLoginData();
[...Load up some Arrays with hardcoded stuff and compute for later use...]
}
public void LoadLoginData() {
OpHandler.post(LoadLoginDataRunnable);
}
private Runnable LoadLoginDataRunnable = new Runnable() {
#Override
public void run() {
if(sharedPreferences==null)
sharedPreferences= PreferenceManager.getDefaultSharedPreferences(context);
sessionID=sharedPreferences.getString("sessionID", null);
if(sessionID!=null) {
postenID = sharedPreferences.getString("postenID", PID_STANDARD);
postenName = sharedPreferences.getString("postenName", PID_STANDARD);
context.QuickToast(sessionID, postenName, postenID);
}
}
};
context is my MainActivity, I gave the operator a reference so I could send Toasts for Debugging.
But now, the Runnables seem to not run or complete, any Log.e or Log.d stuff doesn't arrive in the console.
After some googeling and stackoverflowing, everyone is just always explaining what the difference is between Handlers, Asynctask, and Threads. And the multitask examples always only show something like new Thread(new Runnable{run(task1)}).start times 3 with different tasks.
And so became my big question:
How to correctly, over a longer time (~lifecycle of the MainActivity), with different tasks, use a background thread?
Edit: to clarify, I would also like a direct solution to my special problem.
Edit 2: after reading nikis comment (thank you), the simple answer seems to be "use HandlerThread instead of thread". Will try that as soon as I get home.
Trying a HandlerThread now. It seems my OpHandler, initialized in run(), gets destroyed or something after run() has finished, not sure whats up here (this is btw another mystery of the kind I hoped would get answered here). I get a NullpointerException as soon as I try to use it after run() has finished.
Make your worker thread own a queue of tasks. In the run() method, just pop a task from the queue and execute it. If the queue is empty, wait for it to fill.
class Operator extends Thread
{
private Deque<Runnable> tasks;
private boolean hasToStop=false;
void run()
{
boolean stop=false;
while(!stop)
{
sychronized(this)
{
stop=hasToStop;
}
Runnable task=null;
synchronized(tasks)
{
if(!tasks.isEmpty())
task=tasks.poll();
}
if(task!=null)
task.run();
}
}
void addTask(Runnable task)
{
synchronized(tasks)
{
tasks.add(task);
}
}
public synchronized void stop()
{
hasToStop=true;
}
}
In android why should we use a asyntask and service, instead of using a new thread() and write the necessary background functionality?
I know that we should not run long running operations like downloading a file from server on the mainthread aka UI thread. And should use a asynctask or service.
But why cant we create a new thread() {which is eventually a new thread other than the main thread} and write necessarily long running operation in that thread.
why did google create the AsyncTask and Service without suggesting to use the regular New Thread()???
thanks in advance
edit1:
may be i wasn't clear in my question or not sure, if i am, even now. help me out.
i get it, the whole point starts from
Do not block the UI thread
Do not access the Android UI toolkit from outside the UI thread
why ?
1.how much can the UI thread handle ? how can we determine a breakpoint? how is a ANR point determined? can we track?
2. when a service component handles long running operations why can't a activity component handle?
Remember that if you do use a service, it still runs in your application's main thread by default, so you should still create a new thread within the service if it performs intensive or blocking operations
http://developer.android.com/guide/components/services.html
the above statement is from android documentation.
3.why cant a service start in a new thread straight away, if we are so concerned about main thread? don't get me wrong in question 3, i am trying to understand the advantage of starting the service in main thread. by default.
in the above statement , does it suggest the main thread's ability to start and handle a service's long running operation load? if so does it contradict with question 1.
Well let's look how you'd perform a simple task using a Thread.
The first step is to create a Thread using a Runnable. Something like this:
private void fetchResultsAsync() {
Runnable runner = new Runnable() {
#Override
public void run() {
List<String> results = fetchResultsFromWebServer();
}
};
new Thread(runner).run();
}
The thing is, we need to show the results so it would actually be more like this:
private void fetchResultsAsync() {
Runnable runner = new Runnable() {
#Override
public void run() {
List<String> results = fetchResultsFromWebServer();
workFinished(results);
}
};
new Thread(runner).run();
}
private void workFinished(List<String> results) {
// show the results on the UI
}
It looks good, but there's a problem; the callback method (workFinished) has to update the UI. If we do this from any non-main thread, there will be big problems. We need a thread-safe way to call that method, which is what Handlers are for. Let's also throw in a method for updating our progress, which is very common. The code would now look like this:
private final Handler myHandler = new Handler();
private void fetchResultsAsync() {
Runnable runner = new Runnable() {
#Override
public void run() {
List<String> results = fetchResultsFromWebServer();
workFinished(results);
}
};
new Thread(runner).run();
}
private void showProgress(int result) {
myHandler.post(new Runnable() {
#Override
public void run() {
// update a progress bar here
}
});
}
private void workFinished(final List<String> results) {
myHandler.post(new Runnable() {
#Override
public void run() {
// show the results on the UI
}
});
}
Compare this to the implementation using an AsyncTask:
private void fetchWithTask() {
new AsyncTask<Void, Integer, List<String>>() {
#Override
protected List<String> doInBackground(Void... params) {
return fetchResultsFromWebServer();
}
#Override
protected void onPostExecute(List<String> strings) {
// show the results on the UI
}
#Override
protected void onProgressUpdate(Integer... values) {
// update a progress bar here
}
}.execute();
}
It doesn't differ much by lines of code, but it's much more obvious what needs to happen and where. It protects you from nasty mistakes like forgetting to wrap UI-touching code in a Runnable that has to be posted to a UI-Thread-owned Handler.
Now imagine that you have several different types of small background tasks that need to be performed. It would be very easy to call the wrong showProgress or workFinished method from the wrong background Thread because you have to plug all those pieces together yourself.
There's also a very nasty bug lurking in the use of Handler's default constructor. If the containing class is first referenced by a non-UI thread during runtime, the Handler would belong to that Thread. AsyncTask hides always does things on the correct Thread. This is hard to catch!
At first blush AsyncTasks don't seem all that useful, but the callback plumbing is where they really pay off in spades.
"instead of using a new thread() and write the necessary background functionality?"
Why rewrite the background functionality? AsyncTask does it for you. As njk2 mentioned a Service is not really a fair comparison, though IntentService automatically creates a new thread for you in onHandleIntent().
edit: To answer your other questions, blocking the UI thread, will block all user interaction and the app will appear to "freeze". Definitely not something we want to do at all.
I think this is a beginner (me) question, then for you guys is easy to answer.
I have this method:
public void onQuantityTextChange(final int value)
{
new Thread(new Runnable() {
public void run() {
addProductToCart(value);
view.post(new Runnable() {
public void run() {
updateTotals();
}
});
}
}).start();
}
My question is: this peace of code:
view.post(new Runnable() {
public void run() {
updateTotals();
}
is executed only when this addProductToCart(value); method is executed(finished)? or is it more safe to use AsyncTasks with doInBackground() and onPostExecute()?
It is always executed after: addProductToCart(value);
But if that function starts a Thread or AsyncThread or similar then the function will return before that task finishes.
To summarize: nobody can answer without the contents of addProductToCart
That largely depends on whether or not your method addProductToCart(value) starts another thread of its own. If it does, then there's no guarantee as the thread will start and finish as the system sees fit. If not, then you will not call view.post(...) until that thread is complete.
Another thing to watch out for depending on what you're trying to accomplish is the method inside view.post(...) is not guaranteed to run immediately. What this method does is put Runnable objects inside a message queue. This means, this runnable won't execute until the other elements in the message queue execute first. Secondly, the message queue can run at any time meaning even if this is the first Runnable in the queue it will start eventually, but not necessarily immediately.
I've found the following code does not work because the while loop steals the lock indefinitely:
public void run()
{
while(true)
{
synchronized(run)
{
if (!run) break;
[code]
}
}
}
public void stopRunning()
{
synchronized(run)
{
run = false;
}
}
My goal is to ensure that I don't return from a stopRunning() command until I know that my run() function is no longer actually running. I'm trying to prevent the run function from continuing to reference other things that I'm in the process of destroying. My first thought then is to add a line of code such as Thread.sleep(100) prior to synchronized(run) in order to ensure that it releases the lock. Is this the recommended practice or am I overlooking something [stupid/obvious]?
Thanks!
If you just need stopRunning() to block until run() finishes doing stuff, you could just use a CountDownLatch set to 1. Call it stoppedSignal or something, and in run() you can call stoppedSignal.countDown() when it is finished. In stopRunning you can then set your condition for run() to finish and then call stoppedSignal.await(). It won't proceed until run() "releases" the latch by counting down. This is just one way to do it that would be a bit neater. All the synchronized block stuff that be got rid of.
Beware of the "synchronized" keyword - it's a very blunt and old tool. There are some wonderful things in the concurrency package that fulfil specific purposes much more neatly. "Concurrency In Practice" is a fantastic book on it.
Would something like this suffice?
public void run()
{
while(run)
{
[code]
}
onRunStopped();
}
public void stopRunning()
{
run = false;
}
public void onRunStopped()
{
// Cleanup
}
while synchronized(run) will lock run, you can use run.wait() to freeze the thread run() is executed in.
in another thread, use run.notify() or run.notifyAll() to get run() to continue.
synchronized is used to sync between threads. use it only if there is a potential race condition between 2 or more of them.
Ensure the 'run' object is the same from both point in the code.
The while loop should be synchronizing to the same object as the stopRunning() method.
The while loop is not hogging the lock, it is more likely that the two pieces of code could be referencing a different object. But I cannot tell because the run object is not shown in the code.
There are probably more elegant solutions, but I believe you could solve it with the changes bellow:
private boolean lock;
public void run()
{
while(true)
{
synchronized(lock)
{
if (!run) break;
[code]
}
}
}
public void stopRunning()
{
run = false;
synchronized(lock){ }
}