0

我正在用声音和视觉闪烁在 android 中构建节拍器,当然这两者都需要同步。问题是音频处理发生在后台线程中,我们都非常清楚“只有创建线程层次结构的线程才能更改它的视图”,因此我需要一种方法来让 UI 线程更改视图。那么如何更新 ui 线程与我正在制作的节拍同步呢?这两件事似乎并不同步。有没有比我在下面描述的方法更好的方法来实现这一点?

这是我拥有的当前代码:

public class MetronomeService extends Service implements Runnable
{
    //Thread
    private HandlerThread handlerThread;
    private Handler backgroundHandler;
    private Handler uiHandler
    
    //Interface to the Fragment that owns the views
    @Setter
    private Listener listener;
    
    //Colour view
    private ColourViewManager colour = null;    


    @Override
    public void onCreate()
    {
        handlerThread = new HandlerThread("PlayerHandlerThread", Process.THREAD_PRIORITY_AUDIO);
        handlerThread.start();
        
        //For packages of work in the background
        this.backgroundHandler = new Handler(handlerThread.getLooper());
        
        //To send messages to the UI
        this.uiHandler = new Handler(Looper.getMainLooper())
        {
            @Override
            public void handleMessage(@NonNull Message msg)
            {
                switch (msg.what)
                {
                    case 0:
                    {
                        listener.resetState();
                        break;
                    }
                    case 1:
                    {
                        colour = listener.blink();
                        break;
                    }
                }
            }
        };
        

        super.onCreate();
    }
    
    @Override
    public void run()
    {
        uiHandler.sendEmptyMessage(0);
        audioGenerator.playTrack(bpm);

        while (playingState.get() == TimerState.PLAYING)
        {                
            uiHandler.sendEmptyMessage(1);               

            if (colour == PulsingColourToggleButton.PulsingColour.YELLOW)
            {
                audioGenerator.writeSound(AudioGenerator.TICKING);

            } else if (colour == PulsingColourToggleButton.PulsingColour.RED)
            {
                audioGenerator.writeSound(AudioGenerator.TOCKING);
            }

            audioGenerator.writeSound(AudioGenerator.SILENCE);
        }

        audioGenerator.destroy();
        colour = null;
    }   
    
    
    public void start()
    {
        backgroundHandler.post(this);       
    }   
}

然后在 Fragment 类上,我用一个简单的方法调用服务

service.start()
4

1 回答 1

1

我不知道您到底在做什么,但是要从服务中更改视图,您需要使用LocalBroadcast所以检查一下

在您的服务中创建LocalBradcastManager

val broadcaster = LocalBroadcastManager.getInstance(baseContext)

val intent = Intent("update")
intent.putExtra("orderId", orderId)
intent.putExtra("status", status)
intent.putExtra("data", date)
broadcaster.sendBroadcast(intent)

在你看来

val receiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        try {
            val orderId = intent.getStringExtra("orderId")
            val status = intent.getStringExtra("status")
            val date = intent.getStringExtra("date")

            if (model.details.order_information[0].id.toString() == orderId) {
                if ("Request Order".contains(status!!)) 
                    binding.requestTime.text = date

            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}

LocalBroadcastManager.getInstance(App.instance).registerReceiver(receiver, IntentFilter("update"))

这是您必须执行的逻辑示例

于 2020-12-11T13:44:36.690 回答