Will Runnables block the UI thread?

你离开我真会死。 提交于 2020-01-02 11:06:13

问题


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 these Runnable 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 10 run 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.


回答1:


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




回答2:


Yes. Runnable executing on UI thread will block main thread.

Check if below approach is useful for you.

  1. Create a Handler with Looper from Main :requestHandler
  2. Create a Handler with Looper for main thread : responseHandler and override handleMessage method
  3. post a Runnable task on requestHandler
  4. Inside Runnable task, call sendMessage on responseHandler
  5. This sendMessage result invocation of handleMessage in responseHandler.
  6. 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

android-looper-handler-handlerthread-i




回答3:


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




回答4:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!