【问题标题】:Using HandlerThread and Handler on a separate thread freezes UI thread在单独的线程上使用 HandlerThread 和 Handler 会冻结 UI 线程
【发布时间】:2014-06-11 21:40:36
【问题描述】:

在我的项目中,我想在另一个线程中实现一个计时器,用于倒计时在我的应用程序中执行某个方法所花费的时间,并在花费太多时间时做一些事情。执行 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 调用创建超时计时器。

【问题讨论】:

    标签: android multithreading handler ui-thread


    【解决方案1】:

    试试这个:

    只需将您的第一个可运行对象包装在一个线程中。

    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);
    
    }
    

    【讨论】:

    • 我确实启动了 Handlerthread,我只是忘了添加那行。 MyCommand 类是我试图简化代码中真正发生的事情,我将用更多细节更新问题。
    • 请查看我更新的问题。我不能使用单独的线程来运行 MyCommand,因为它正在执行已经在单独的线程中发生的 API 调用。
    • @mpellegr 你能进一步解释一下你在做什么 api 调用吗?
    • 它是第三方库而不是 android API 调用。我只能说 API 调用无论如何都会在另一个线程上运行,所以我认为将 MyCommand.myRun 字段放在另一个线程上并不是一个好主意。
    • @mpellegr 不可能有自己的线程。如果它有自己的线程,那么您在代码中的某处调用该 API 并运行不同的线程这一事实将无法使用。
    猜你喜欢
    • 1970-01-01
    • 2021-12-21
    • 2012-08-10
    • 2011-06-22
    • 1970-01-01
    • 2016-04-22
    • 1970-01-01
    • 2015-10-23
    • 1970-01-01
    相关资源
    最近更新 更多