在单独的线程上使用HandlerThread和Handler会冻结UI线程

时间:2014-06-11 21:40:36

标签: android multithreading handler ui-thread

在我的项目中,我想在另一个线程中实现一个计时器,该计时器会减少在我的应用程序中执行某个方法所花费的时间,如果花费太多时间就会做一些事情。当执行MyManager.startCommand()方法时,应用程序冻结,我不知道为什么,因为我认为我没有在UI线程上做任何事情。我的代码有什么问题吗?

我最初问过这个问题并没有遇到应用程序冻结,所以我不认为这是因为我正在睡觉: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();
    }
}

我是如何使用MyCommand对象的:

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

所以我基本上是在尝试为该API调用创建超时计时器。

1 个答案:

答案 0 :(得分:1)

试试这个:

将第一个runnable包装在一个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();
}

}

你也忘了开始mHandlerThread

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

}