Вопрос

in my mainActivity, which is the sole activity of my application, I am creating the below handler and running a runnable inside it.

I have some misunderstandings about handlers and where they run.

See the code

Handler handler;

    @Override
    protected void onCreate(Bundle bundle)
    {
      handler = new Handler();
      handler.postDelayed(r , 5000);
    }

    Runnable r = new Runnable()
    {
         @Override 
         public void run() {
              FetchServerAndUpdateStatus(); //network stuff in here
              handler.postDelayed(r , 5000);
         }
    }
  • I assume this code will still run in UI thread and I won't be able to make any network calls in there no ?
  • If yes, what shall I do ? Create and use a seperate thread ?
  • If I created a new thread, How can I run the postdelayed method ? The thread does not have post delayed ?
  • Does not using handler/runnable and using TimerTask and Runnable instead a better approach ? Or, just like the above handler/runnable, that will also run on the UI thread, unless created inside a seperate one.
Это было полезно?

Решение

When you construct a Handler it is bound to the thread it is constructed on.

onCreate() is run on the UI thread so this handler will be bound to the Looper on the main thread, and thus will run on that thread.

If you want a handler you can use on another thread you can construct one. See the looper docs: https://developer.android.com/reference/android/os/Looper.html

Which has this block:

class LooperThread extends Thread {
  public Handler mHandler;

  public void run() {
      Looper.prepare();

      mHandler = new Handler() {
          public void handleMessage(Message msg) {
              // process incoming messages here
          }
      };

      synchronized (this) {
          this.notifyAll();
      }

      Looper.loop();
  }
}

Add this class and then in your onCreate do the following:

mLooperThread = new LooperThread();
mLooperThread.start();
synchronized (mLooperThread) {
  while (null == mLooperThread.mHandler) {
    mLooperThread.wait();
  }
}
mLooperThread.mHandler.postDelayed(r , 5000);

This will cause the runnable to be run NOT on the UI thread, which is probably what you wanted.

For tasks that need to interact with the UI an AsyncTask may be better since it includes a mechanism to run things that touch Views when the task is done on the UI thread, since anything that touches a View must be done on the UI thread.

The other mechanisms for executing on the UI thread are to post to the view itself:

https://developer.android.com/reference/android/view/View.html#post(java.lang.Runnable) or [https://developer.android.com/reference/android/view/View.html#postDelayed(java.lang.Runnable, long)](https://developer.android.com/reference/android/view/View.html#postDelayed(java.lang.Runnable, long))

Or to ask the Activity to run it on the UI for you:

https://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)

Другие советы

  1. It depends on what you do with your handler, you didn't show, how you want to obtain m_handler. If you create it with new Handler(Looper.getMainLooper()), it will run on UI thread.
  2. If you want to run code in background (network operations) you should use AsyncTask
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top