I am trying to understand how UI thread's event queue works. I'm trying to run a code that can be broken into many parts but unfortunately it must run on the UI thread. So, in order to not block the UI thread and receive a ANR I was wondering if I can break that code in many Runnable
objects and run them using runOnUiThread
from another thread.
My question is, will this block the UI thread? If, for example, I have a piece of code that definitely runs in over 5 seconds and I break this code into, let's say 1000 Runnable
objects, and add them to the event queue of the UI thread, will other events get processed by the UI thread between them?
Edit: I think I found a better way to express myself in case the above explanation is confusing.
- The 1000
Runnable
objects was just an example, in actual code I want to have at most 10. - Basically, I want 10
Runnable
objects, each one initialising an Ad network on the UI thread. I want theseRunnable
objects to run one after another, not in parallel. Also, I want the UI thread to be able to process other events between running these objects, so that I don't get an ANR in case running all 10run
methods will take more than 5 seconds.
NOTE: I don't know why initialising Ad networks must be done on the UI thread, but it must, otherwise the app crashes. It also states in some of the networks' sdks' documentation that initialisation must happen on the UI thread. This is why I need to run them one after another on UI thread and I can't run them in parallel in the background.
Also, the app is actually a OpenGl game, so calls to running the Runnable
objects will be made from a GL thread, not the main thread, so they will be added to the event queue, and not executed immediately.
Well, Runnable
inside your runOnUiThread
is just operation in Main Thread
.
Imagine that some simple action like
textView.setText("example");
will block Main Thread for 5 ms. Usually you will not see it.
Now imagine that you have like 1000 same operations for 5 seconds. And every blocks Main Thread
for 5 ms. Simple calculating 5ms * 1000 = 5000ms = 5 seconds. So it will block Main Thread
permamently. But if you have 10 operations you will block only 50 ms, in other words its just 1% of load that you will not feel.
So possible amount of calls depends on size of View
, how hard render is and how fast is device.
P.S. For adepts of AsyncTask
- there is no real difference between runOnUiThread
and AsyncTask
because those 1000 Runnables
will execute in Main Thread
by the same way.
Even if I do same thing inside onCreate method of Activity that will block UI hard
Yes. Runnable
executing on UI thread will block main thread.
Check if below approach is useful for you.
- Create a Handler with Looper from Main :
requestHandler
- Create a Handler with Looper for main thread :
responseHandler
and overridehandleMessage
method post
aRunnable
task onrequestHandler
- Inside
Runnable
task, callsendMessage
onresponseHandler
- This
sendMessage
result invocation ofhandleMessage
inresponseHandler
. - Get attributes from the
Message
and process it, update UI
Sample code:
/* Handler */
Handler requestHandler = new Handler(Looper.getMainLooper());
final Handler responseHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
//txtView.setText((String) msg.obj);
Toast.makeText(MainActivity.this,
"Adwork task is completed:"+(String)msg.obj,
Toast.LENGTH_LONG)
.show();
}
};
for ( int i=0; i<10; i++) {
// Start Adwork task
Runnable myRunnable = new Runnable() {
@Override
public void run() {
try {
/* Your business logic goes here */
// Send some result after computation
String text = "" + (++rId);
Message msg = new Message();
msg.obj = text.toString();
responseHandler.sendMessage(msg);
System.out.println(text.toString());
} catch (Exception err) {
err.printStackTrace();
}
}
};
requestHandler.post(myRunnable);
}
Useful articles:
handlerthreads-and-why-you-should-be-using-them-in-your-android-apps
What you are looking for is an AsyncTask.
These are designed to do some background processing, while the UI thread continues. It will NOT block the UI and will NOT cause ANR.
Within the AsyncTask, is an onPostExecute
method, which allows you to post results back to the UI. So it is not completely detached from the UI Thread. And an onProgressUpdate
for connection during the background processing
Yes, you will feel animation will stop or start shutter if You run heavy operations in Ui thread. It's also depends of how fast device is.
What I would suggest you is to break your code in two parts. One that can be done in background and second that need Ui thread and execute them in AsyncTask.
Use doInBackgroud
method to execute heavy operation and onPostExecute
to update UI.
Note: If you break code into 1000 threads and run them in one moment, then probably You will hit device queue limit. (Break them into 10-50 parts. )
来源:https://stackoverflow.com/questions/45791504/will-runnables-block-the-ui-thread