Android calling a method from a different class from within an AsyncTask - java

Within an Asynctask I call a method, i mean from within doInBackgroud() { ...code goes here ... }, I call a method that is ..
A) .. within the async task class
B) .. in a different class
Is this method-call still executed in the thread of the asynctask?
I am wondering, because it is often said that "only code inside doInBackgroud() { ...code goes here ... } is executed in a different thread.

Calls made (either directly or indirectly) from within doInBackground() are automatically run in the background thread.
There are ways to force some code to run within the main UI thread (for example, see this question), but that has to done explicitly.

Yes, the method call is executed in the thread of the asynctask. The asynctask would be pretty useless if unable to invoke methods on other classes.
Furthermore, if the doInBackground method (frequently used to make web requests) would run in the main thread, the Android would throw an exception (NetworkOnMainThreadException).

I am wondering, because it is often said that "only code inside doInBackgroud() { ...code goes here ... } is executed in a different thread.
When your application is started up, a thread is created called the UI thread (also known as the ‘main’ thread). This thread dispatches all of the events to the widgets and whatnot on your application.
The AsyncTask will execute onPreExecute and onPostExecuteon the UI thread. doInBackground() on the other-hand is invoked on the background thread and will return back to the main thread once completed.

Related

Does View.OnTouchListener run on other thread than the UI thread?

If I have a class object Square (that is not the MainActivity, but MainActivty creates Square objects) that implements View.OnTouchListener, does the onTouch() method within Square run on the UI thread or another thread?
It seems like it is running on another thread, since I cannot update the UI from within the onTouch() method without calling runOnUiThread() on my MainActivity object.
=== EDIT GOES BELOW ========================
I logged Thread.currentThread().toString() as suggested by #pskink, and got the following result:
onCreate() in MainActivity: Thread[main,5,main]
onTouch() in Square: Thread[main,5,main]
So, it is clear now, the onTouch() method that I have running in Square, runs on the UI/main thread.
Thanks everyone for the help! :-)
Does View.OnTouchListener run on other thread than the UI thread?
No. it is supposed to called in UI thread
please use below code to know if current thread is UI/Main thread or not.
if(Looper.myLooper() == Looper.getMainLooper()) {
// Current Thread is Main Thread.
}
or you can also use this
if(Looper.getMainLooper().getThread() == Thread.currentThread()) {
// Current Thread is Main Thread.
}
From my perspective it is running on UI thread if you still have a doubt you can put above code inside onTouchListener and check it.
Does View.OnTouchListener run on UI thread?
Yes. 100%. System will be calling all the methods on UI thread by default.
But you can perform operations on worker thread inside onTouch() method.
Ps,
UI changes must be performed on UI Thread. Consider calling runOnUiThread while you need to update an UI from worker thread. You should consider use threading to avoid ANR (Application not responding). A good start is AsyncTask, that has it own method to do logic in a separate thread and update the UI on the Main Thread.

Loopers - Handlers - Threads

So, I am working with some code that performs seemingly asynchronous tasks and uses the typical callback/listener model to receive callbacks.
My problem is that sometimes the callbacks never fire if I hold up the thread that called the operation.
Considering the following snippet of code:
doAsync(new Callback(){
// Callback here
});
The internals of doAsync() are using a handler and the main looper.
Considering I call this code from Thread A can somebody please outline the effects of blocking the Thread A right after this call.
Also, what are the effects of running the Handler on main looper and local looper will it determine the thread that the above callback is executed on? I ask this because if I block Thread A then the callback never executes.
calling in Async Task does not block the main thread...doInBackground method executes the operations in background thread...if you want to update the UI after your execution in background has completed you must override the onPostExecute() method....there are some other hooks for UI thread too like onProgressUpdate and OnCancelled in AsyncTask....please check the java doc of AsyncTask for details

Android service's method called in different thread. Does it still run on the main thread?

If I am understanding correctly, Android Services, by default, run on the main UI thread.
Thus, for any off-the-main-thread operation to work, I found people suggesting that one starts a separate thread in the Service.
However, my question is if a Service's method is called in another thread, i.e. AsyncTask or new Thread(...).start();, does the Service's method run in the calling thread? or does it run on the main thread, which supposedly the Service is running in?
In other words,
new Thread(new Runnable() {
#Overrde
public void run() {
myAndroidService.doSomething();
}
}).start();
would MyAndroidService#doSomething() be called in this new Thread?
A method is always run in the thread that invokes it.
A method doesn't really belong to any thread, so yes, even though the method is defined in your Service it will be executed in the AsyncTask thread, not the main thread that your Service is running in.
Yes, as Martin has metioned above.
Also, you can check out a method's thread info by:
private void doSomething(){
Log.i(TAG, "I'm doing something in thread " + Thread.currentThread().toString());
}

Thread as constructor or run()

Is there any difference between creating a thread using the run() method as opposed to using the a constructor?
I noticed that I can start the thread and it acts the same in both ways.
new Thread MyThread().start
For example, as a constructor:
public class MyThread extends Thread{
public MyThread(){
// Do something
}
}
or as the run() method
public class MyThread extends Thread{
public void run(){
// Do something
}
}
Is there any difference between constructor or run()? Thanks!
It does not act the same in both cases
These cases are entirely different.
First, you probably need to learn about Threads and non-blocking processes. A Thread is used to do something asynchronously. So if you wanted to do some background task whilst doing something else then you would use a Thread. A good example is a GUI; you need one Thread to listen for GUI events (mouse clicks, button presses) and another to do any long running processing.
Now, onto your examples.
In Java a Thread consists of a run method that executes asynchronously when the start method is called. So when overriding Thread you change the run method. In reality you should never override Thread, you should use the constructor that takes a Runnable. There are many reasons for this, you should read up on concurrency.
Any code you place in your Thread constructor will be executed in the Thread that calls your constructor so this is not called asynchronously.
If you put the code in the run method, a new thread will be started upon invocation of start, which uses the run method as its starting point. If you put the code in the constructor, however, it will be run in the same thread as that which invoked the constructor, because a constructor is a special case of a method. Thus, if you want to start something in a new thread, put it in run, otherwise, put it in the constructor. Also, if you want to start a thread, never call Thread.run, because of the same reason not to put code in the constructor. Always call Thread.start().
The key difference is this:
The code in your constructor is executed immediately and synchronously when the constructor is invoked.
The program will stop and wait for that code to complete before moving on to the next line of code.
If you put the code inside run() method AND use Thread.start(), the code will be executed in a separate thread (i.e. it will run asynchronously).
Your program will continue to execute (moving to the next line of code immediately) while the code in your run() method runs in parallel.
This is helpful if the code in run() takes a very long time to execute.
That's because your program can continue to do other things while it waits for the thread to finish its work.
There is a difference. The constructor that creates the Runnable or subclass thereof runs in the main thread.
When starting a thread using:
new Thread(myRunnable).start();
you'll actually have run( of myRunnable run in the new thread.
NB You'll want to have a reference to the thread object in many cases. This code example is merely illustrative
On another note, never, ever, ever, give a thread this if starting within a constructor. Your computer could explode, or asphyxiation, drowning, or poisoning may occur.

How to know if this thread is a UI Thread

Is there any way on Android to know, if the thread running my code, is the UI Thread or not ? In swing there was SwingUtilities.isEventDispatchThread() to tell me if i am on the UI Thread, or not. Is there any function in the Android SDK that lets me know this ?
Answer borrowed from here: How to check if current thread is not main thread
Looper.myLooper() == Looper.getMainLooper()
Any Android app has only one UI thread, so you could somewhere in the Activity callback like onCreate() check and store its ID and later just compare that thread's ID to the stored one.
mMainThreadId = Thread.currentThread().getId();
Anyway, you can omit checking if you want to do something on the UI thread and have any reference to Activity by using
mActivity.runOnUiThread( new Runnable() {
#Override
public void run() {
...
}
});
which is guaranteed to run on current thread, if it's UI, or queued in UI thread.
Yes, there is a way.
Check the current thread object against main lopper's thread object. Main looper is always in the UI thread.
boolean isOnUiThread = Thread.currentThread() == Looper.getMainLooper().getThread();
Hum actually due to Android architecture, all Activities run in the main thread, ie the UI thread. So when you are coding an activity, everything that is in your Activity is in the UI thread.
That is why in Honeycomb an error have been added when you are making network calls in the main thread : it totally blocks the UI.
So by default you are in fact always working in the UI thread.
Another thing : unless you explicitely ask it to be in another thread, a Service will operate on the same thread as the activities of its application.
So, what to do ?
When you have to do heavy calculation in your activity; one solution is to use an AsyncTask (a class designed to allow you to easily use another thread). The code in onExecute() is run in another thread (but be cautious postExecute runs in your main thread). Another one is to manually start a new thread when AsyncTask is not really adapted.
If you create a service that does costly background tasks, make it run in another thread with the android:process=":my_process" attribute of the manifest. You will need to create an AIDL to communicate with this separated service, but it is not a complicated task.
Many objects, like for example the MediaPlayer, have Async variations of their methods. Try to to always use them.
Put a breakpoint where you want to check and, when it gets hit, check if you can interact with your UI (ie, if the UI is not frozen). If you can't interact with the UI then you are in the UI Thread, otherwise you are in a background thread.

Categories