mpellegr
mpellegr

Reputation: 3182

Using HandlerThread and Handler on a separate thread freezes UI thread

In my project, I want to implement a timer in another thread that counts down the time spent executing a certain method in my application, and do something if it is taking too much time. When executing the MyManager.startCommand() method, the application is freezing and I don't know why since I think I am not doing anything on the UI thread. Is there anything wrong with my code?

I had originally asked this question and was not experiencing an app freeze, so I don't think it's because I'm sleeping the thread: Runnable posted in another runnable not executed.

public class MyManager{
    private MyManager sInstance;
    private HandlerThread mHandlerThread;
    private Handler mHandler;
    private Runnable mTimeoutTimer;

    public static MyManager getInstance(){
        if(sInstance == null){
            sInstance = new MyManager();
        }
        return sInstance;
    }

    private MyManager(){
        mHandlerThread = new HandlerThread("mHandlerThread");
        mHandlerThread.start();
        mHandler = new Handler(mHandlerThread.getLooper());
        mTimeoutTimer = new Runnable() {
            @Override
            public void run() {
                Log.e(“RUNNABLE RUNNING!”);
            }
    };

    public class MyCommand {
       private Runnable myRun;

       public MyCommand(){
           myRun = new Runnable() {
               @Override
               public void run() {
                   MyManager.getInstance().startTimeoutTimer();
                   MyCommand.this.run();
               }
           };
       }

       public void execute() {
           myRun.run();
       }

       abstract public void run();
    }


    private void startTimeoutTimer(){
        mHandler.post();
    }


    public void startCommand(){
        new MyCommand().execute();
    }
}

And how I'm using a MyCommand object:

MyCommand command =
new MyCommand() {
    @Override
    public void run() {
        //make api call that happens in another thread
    }
};

So I am basically trying to create the timeout timer for that API call.

Upvotes: 1

Views: 924

Answers (1)

Rod_Algonquin
Rod_Algonquin

Reputation: 26198

Try this:

Just wrap your first runnable in a Thread.

public class MyManager{
private MyManager sInstance;
private HandlerThread mHandlerThread;
private Handler mHandler;
private Runnable mTimeoutTimer;

public static MyManager getInstance(){
    if(sInstance == null){
        sInstance = new MyManager();
    }
    return sInstance;
}

private MyManager(){
    mHandlerThread = new HandlerThread();
    mHandler = new Handler(mHandlerThread.getLooper());
    mTimeoutTimer = new Runnable() {
        @Override
        public void run() {
            Log.e(“RUNNABLE RUNNING!”);
        }
};

public class MyCommand {
    private Thread th;
    private Runnable myRun;

   public MyCommand(){
       myRun = new Runnable() {
           @Override
           public void run() {
               MyManager.getInstance().startTimeoutTimer();

               try {
                   Thread.sleep(COMMAND_TIMEOUT_MILLIS * 3);
               } catch (InterruptedException e) {}

               MyCommand.this.execute();
           }
       };
       th = new Thread(myRun);
   }

   public void execute() {
       th.start();
        mHandler.postDelayed(mTimeoutTimer);
   }
}


private void startTimeoutTimer(){
    mHandlerThread.start();
    mHandler.postDelayed(mTimeoutTimer);

}


public void startCommand(){
    new MyCommand().execute();
}

}

Also you forgot to start the mHandlerThread

    private void startTimeoutTimer(){
    mHandlerThread.start();
    mHandler.postDelayed(mTimeoutTimer);

}

Upvotes: 1

Related Questions