You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

批量合成TTS音频后更新UI触发Looper线程错误求助

解决"Animators may only be run on Looper threads"错误

这个问题的核心原因很明确:UtteranceProgressListener的回调方法(比如OnDone)是在后台线程执行的,而Android要求所有UI操作必须在主线程(UI线程)中完成。你之前尝试把FAB设为全局变量没用,就是因为操作它的线程还是不对,和变量是否全局无关。

具体解决方案:切换到主线程执行UI操作

你可以利用Activity的RunOnUiThread方法,把更新UI的逻辑包裹在里面,确保代码在主线程运行。下面是修改后的关键代码:

1. 修改UtteranceProgressListener1的OnDone方法

把调用AudioConvertionResults的逻辑放到RunOnUiThread中:

public override void OnDone(String utteranceId)
{
    Log.Info("101029", "OnDone: " + total.ToString());
    total++;
    // 切换到主线程执行UI相关的检查和操作
    _parent.RunOnUiThread(() => 
    {
        _parent.AudioConvertionResults(total);
    });
}

2. 确保AudioConvertionResults中的UI操作安全

虽然上面已经切换了线程,你也可以简化这个方法,直接在主线程里处理:

public bool AudioConvertionResults(int CompInt)
{
    Log.Info("101029", "ComInt: " + CompInt.ToString() );
    if (CompInt >= 10)
    {
        try
        {
            Log.Info("101029", "Triggered at " + CompInt.ToString());
            FloatingActionButton FAB = FindViewById<FloatingActionButton>(Resource.Id.fab);
            FAB.Visibility = ViewStates.Visible;
        }
        catch(Exception X)
        {
            Log.Info("101029", "Error Triggering? "+X.Message);
            return false;
        }
        return true;
    }
    else
    {
        Log.Info("101029", "DID NOT Trigger at " + CompInt.ToString());
        return false;
    }
}

为什么这样能解决问题?

RunOnUiThread会把传入的Action提交到主线程的消息队列中,等待主线程空闲时执行,这样所有的UI操作(比如查找控件、设置可见性)就都在正确的线程上运行了,自然就不会再出现"Animators may only be run on Looper threads"的错误。

另外,如果你习惯用Handler,也可以创建一个主线程的Handler来发送消息处理UI操作,效果是一样的,不过RunOnUiThread在Activity中使用更简洁。

内容的提问来源于stack exchange,提问作者Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:50:07