在android上,播放按钮图标在歌曲完全播放之前不会改变

在android上,播放按钮图标在歌曲完全播放之前不会改变,android,Android,我有一个图像按钮,它兼作播放和停止按钮。我需要在用户第一次单击按钮时更改按钮中的图像,以便它现在看起来像一个停止按钮。但这不会发生,直到线程完成播放歌曲 ImageButton Sound; public void onClick(View v) { selectRandomSong(); Sound.setBackgroundResource(R.drawable.stop); v.invalidate(); if(playing) stop()

我有一个图像按钮,它兼作播放和停止按钮。我需要在用户第一次单击按钮时更改按钮中的图像,以便它现在看起来像一个停止按钮。但这不会发生,直到线程完成播放歌曲

ImageButton Sound;
public void onClick(View v) {
    selectRandomSong();
    Sound.setBackgroundResource(R.drawable.stop);
    v.invalidate();
    if(playing)
        stop();
    else
        play();
    Sound.setBackgroundResource(R.drawable.play);
}
setBackground
不会反映在视图上,因为无效不会发生。我不确定stop()和play()是如何实现的,但根据您的描述,它们似乎阻止了UI线程,因此按钮背景永远不会改变。在单独的线程中运行这些函数可以解决阻塞问题,但您只能在UI线程上更新后台资源。为了解决这个问题,可以使用Activity.runOnUiThread()调用

这段代码不是线程安全的(而且未经测试),但应该为您提供一个良好的起点

ImageButton Sound;
public void onClick(View v) {

    //Kick off a new thread to play the song without blocking the UI thread
    Thread playSongThread = new Thread() {
        public void run() {
            selectRandomSong();
            setBackgroundResource(R.drawable.stop);
            //v.invalidate(); //shouldn't be neccessary
            if(playing)
                stop();
            else
                play();
            setBackgroundResource(R.drawable.play);
        }       
    };      
    playSongThread.start();
}

/**
 * Sets the background resource using the UI thread
 * @param id Resource ID to set the background to
 */
private void setBackgroundResource(final int id)
{
    this.runOnUiThread(new Runnable()
    {
        public void run()
        {
            Sound.setBackgroundResource(id);                
        }
    });
}
我不确定stop()和play()是如何实现的,但根据您的描述,它们似乎阻止了UI线程,因此按钮背景永远不会改变。在单独的线程中运行这些函数可以解决阻塞问题,但您只能在UI线程上更新后台资源。为了解决这个问题,可以使用Activity.runOnUiThread()调用

这段代码不是线程安全的(而且未经测试),但应该为您提供一个良好的起点

ImageButton Sound;
public void onClick(View v) {

    //Kick off a new thread to play the song without blocking the UI thread
    Thread playSongThread = new Thread() {
        public void run() {
            selectRandomSong();
            setBackgroundResource(R.drawable.stop);
            //v.invalidate(); //shouldn't be neccessary
            if(playing)
                stop();
            else
                play();
            setBackgroundResource(R.drawable.play);
        }       
    };      
    playSongThread.start();
}

/**
 * Sets the background resource using the UI thread
 * @param id Resource ID to set the background to
 */
private void setBackgroundResource(final int id)
{
    this.runOnUiThread(new Runnable()
    {
        public void run()
        {
            Sound.setBackgroundResource(id);                
        }
    });
}

你的“声音”是什么?如果是按钮,你应该使用视图v引用,而不是将背景设置为一次引用并使另一个无效…声音是他/她的图像按钮,就在代码部分的顶部。你不需要使视图无效,但我怀疑你不是在玩线程。如果你不想让我们帮你的话,你就得写些代码。我想,音乐播放最好是异步的。这可能会解决问题。是的,一个单独的执行线程工作了。你的“声音”是什么?如果是按钮,你应该使用视图v引用,而不是将背景设置为一次引用并使另一个无效…声音是他/她的图像按钮,就在代码部分的顶部。你不需要使视图无效,但我怀疑你不是在玩线程。如果你不想让我们帮你的话,你就得写些代码。我想,音乐播放最好是异步的。这可能会解决问题。是的,一个单独的执行线程起作用了。你搞定了!!!它就像一个符咒。。。但是你能解释一下为什么这段代码是线程不安全的吗?因为这是多线程的,所以在另一个线程更改布尔值之前,一个线程可能会根据“播放”布尔值做出决定。因此,如果用户连续几次快速按下按钮,你可能会看到奇怪的行为。你搞定了!!!它就像一个符咒。。。但是你能解释一下为什么这段代码是线程不安全的吗?因为这是多线程的,所以在另一个线程更改布尔值之前,一个线程可能会根据“播放”布尔值做出决定。因此,如果用户连续快速按下按钮数次,您可能会看到奇怪的行为。