【问题标题】:SetBackgroundResource() delayed?SetBackgroundResource() 延迟?
【发布时间】:2017-05-28 19:48:41
【问题描述】:

我正在 Android 中为一个 uni 项目实现 Simon Says,作为 Audiogames 套件应用程序的一部分。我正在尝试生成一个由 5 个(仅作为开始测试)按钮播放的随机序列,并且一切顺利,除了一件事:按钮在它们应该亮起的时候没有亮起(当它们在序列中的种子生成时)但是相反,它们确实会在世代结束时一起点亮。

遵循我的 Java 和 XML 的完整代码(这有点混乱和不完整,所以我会指出对我来说很麻烦的部分)

Java 源码

package it.unimi.di.lim.audiogames;

import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;

import java.util.LinkedList;
import java.util.Random;

public class Game2PlayActivity extends AppCompatActivity {

    private int mScore = 0;
    private LinkedList<Integer> temp = new LinkedList<>();

    private MediaPlayer mCMediaPlayer;
    private MediaPlayer mDMediaPlayer;
    private MediaPlayer mEMediaPlayer;
    private MediaPlayer mFMediaPlayer;

    private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mp) {
            releaseMediaPlayer(mp);
            turnOffButton(mp);
        }
    };

    private void releaseMediaPlayer(MediaPlayer mediaPlayer) {
        if (mediaPlayer != null) {
            mediaPlayer.release();
        }
    }

    private void turnOffButton(MediaPlayer mp) {
        Button mc_button = (Button) findViewById(R.id.c_button);
        Button md_button = (Button) findViewById(R.id.d_button);
        Button me_button = (Button) findViewById(R.id.e_button);
        Button mf_button = (Button) findViewById(R.id.f_button);
        if(mp == mCMediaPlayer) {
            mc_button.setBackgroundColor(getResources().getColor(R.color.game2_c_off));
        } else if (mp == mDMediaPlayer) {
            md_button.setBackgroundColor(getResources().getColor(R.color.game2_d_off));
        } else if (mp == mEMediaPlayer) {
            me_button.setBackgroundColor(getResources().getColor(R.color.game2_e_off));
        } else {
            mf_button.setBackgroundColor(getResources().getColor(R.color.game2_f_off));
        }
    }

    private void playButton(int i) {
        char j;
        if(i==0)
            j='0';
        else if(i==1)
            j='1';
        else if(i==2)
            j='2';
        else
            j='3';
        Button mc_button = (Button) findViewById(R.id.c_button);
        Button md_button = (Button) findViewById(R.id.d_button);
        Button me_button = (Button) findViewById(R.id.e_button);
        Button mf_button = (Button) findViewById(R.id.f_button);
        switch(j) {
            case '0':
                mc_button.setBackgroundResource(R.color.game2_c_on);
                //mCMediaPlayer = MediaPlayer.create(Game2PlayActivity.this, R.raw.c_sound);
                //mCMediaPlayer.start();
                //mCMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                 //   @Override
                 //   public void onCompletion(MediaPlayer mp) {
                 //       mCMediaPlayer.release();
                 //   }
                //});
                break;
            case '1':
                md_button.setBackgroundResource(R.color.game2_d_on);
                //mDMediaPlayer = MediaPlayer.create(Game2PlayActivity.this, R.raw.d_sound);
                //mDMediaPlayer.start();
                //mDMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                //    @Override
                //    public void onCompletion(MediaPlayer mp) {
                //        mDMediaPlayer.release();
                //    }
                //});
                break;
            case '2':
                me_button.setBackgroundResource(R.color.game2_e_on);
                //mEMediaPlayer = MediaPlayer.create(Game2PlayActivity.this, R.raw.e_sound);
                //mEMediaPlayer.start();
                //mEMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                //    @Override
                //    public void onCompletion(MediaPlayer mp) {
                //        mEMediaPlayer.release();
                //    }
                //});
                break;
            case '3':
                mf_button.setBackgroundResource(R.color.game2_f_on);
                //mFMediaPlayer = MediaPlayer.create(Game2PlayActivity.this, R.raw.f_sound);
                //mFMediaPlayer.start();
                //mFMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                //    @Override
                //    public void onCompletion(MediaPlayer mp) {
                //        mFMediaPlayer.release();
                //    }
                //});
                break;
        }
    }

    private void createSequence(int i) {
        Random rand = new Random();
        for(int j = 0; j < i; j++) {
            int seed = rand.nextInt(4);
            temp.add(seed);
            playButton(seed);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        releaseMediaPlayer(mCMediaPlayer);
        releaseMediaPlayer(mDMediaPlayer);
        releaseMediaPlayer(mEMediaPlayer);
        releaseMediaPlayer(mFMediaPlayer);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_game2_play);

        Button mc_button = (Button) findViewById(R.id.c_button);
        Button md_button = (Button) findViewById(R.id.d_button);
        Button me_button = (Button) findViewById(R.id.e_button);
        Button mf_button = (Button) findViewById(R.id.f_button);

        if (Build.VERSION.SDK_INT >= 21) {
            Window window = this.getWindow();
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            window.setStatusBarColor(this.getResources().getColor(R.color.game2Dark));
            window.setNavigationBarColor(this.getResources().getColor(R.color.game2Primary));
        }

        android.support.v7.app.ActionBar bar = getSupportActionBar();
        bar.setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.game2Primary)));

        mc_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                playButton(0);
                int check = temp.poll();
                if(check!=0) {
                    Intent gameOver = new Intent(Game2PlayActivity.this, Game2Activity.class);
                    gameOver.putExtra("score", mScore);
                    startActivity(gameOver);
                }
                if(temp.size() == 0) {
                    mScore++;
                    TextView score = (TextView) findViewById(R.id.game2_score);
                    score.setText(Integer.toString(mScore));
                }
            }
        });

        md_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                playButton(1);
                int check = temp.poll();
                if(check!=1) {
                    Intent gameOver = new Intent(Game2PlayActivity.this, Game2Activity.class);
                    gameOver.putExtra("score", mScore);
                    startActivity(gameOver);
                }
                if(temp.size() == 0) {
                    mScore++;
                    TextView score = (TextView) findViewById(R.id.game2_score);
                    score.setText(Integer.toString(mScore));
                }
            }
        });

        me_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                playButton(2);
                int check = temp.poll();
                if(check!=2) {
                    Intent gameOver = new Intent(Game2PlayActivity.this, Game2Activity.class);
                    gameOver.putExtra("score", mScore);
                    startActivity(gameOver);
                }
                if(temp.size() == 0) {
                    mScore++;
                    TextView score = (TextView) findViewById(R.id.game2_score);
                    score.setText(Integer.toString(mScore));
                }
            }
        });

        mf_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                playButton(3);
                int check = temp.poll();
                if(check!=3) {
                    Intent gameOver = new Intent(Game2PlayActivity.this, Game2Activity.class);
                    gameOver.putExtra("score", mScore);
                    startActivity(gameOver);
                }
                if(temp.size() == 0) {
                    mScore++;
                    TextView score = (TextView) findViewById(R.id.game2_score);
                    score.setText(Integer.toString(mScore));
                }
            }
        });


        Button start_button = (Button) findViewById(R.id.game2_start_button);
        start_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                createSequence(5);
            }
        });
    }
}

XML 源

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:orientation="vertical"
    tools:context=".Game1PlayActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:text="@string/game2_score"
        android:textSize="16sp"
        android:padding="16dp"
        android:gravity="bottom"
        android:textAlignment="center" />

    <TextView
        android:id="@+id/game2_score"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1.2"
        android:text="0"
        android:textSize="48sp"
        android:padding="16dp"
        android:gravity="top"
        android:textAlignment="center" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="0.8"
        android:text="@string/game2_criteria"
        android:textSize="16sp"
        android:padding="16dp"
        android:gravity="bottom"
        android:textAlignment="center" />

    <Button
        android:id="@+id/game2_start_button"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:text="@string/game2_start"
        android:layout_marginTop="8dp"
        android:layout_marginLeft="64dp"
        android:layout_marginRight="64dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2">

        <Button
            android:id="@+id/c_button"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@color/game2_c_off"
            android:layout_margin="16dp"
            android:text="@string/game2_c" />

        <Button
            android:id="@+id/d_button"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@color/game2_d_off"
            android:layout_margin="16dp"
            android:text="@string/game2_d" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2">

        <Button
            android:id="@+id/e_button"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@color/game2_e_off"
            android:layout_margin="16dp"
            android:text="@string/game2_e" />

        <Button
            android:id="@+id/f_button"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@color/game2_f_off"
            android:layout_margin="16dp"
            android:text="@string/game2_f" />

    </LinearLayout>

</LinearLayout>

----------------------------------------------- --------------------------------

所以基本上我要做的是通过单击“开始”按钮生成序列,这是onClickListener(5 仅用于测试目的)

Button start_button = (Button) findViewById(R.id.game2_start_button);
    start_button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            createSequence(5);
        }
    });

这会触发createSequence()方法如下

private void createSequence(int i) {
    Random rand = new Random();
    for(int j = 0; j < i; j++) {
        int seed = rand.nextInt(4);
        temp.add(seed);
        playButton(seed);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

到目前为止一切都很好。我认为在我糟糕的编程经验中失败的是PlayButton() 方法

private void playButton(int i) {
    char j;
    if(i==0)
        j='0';
    else if(i==1)
        j='1';
    else if(i==2)
        j='2';
    else
        j='3';
    Button mc_button = (Button) findViewById(R.id.c_button);
    Button md_button = (Button) findViewById(R.id.d_button);
    Button me_button = (Button) findViewById(R.id.e_button);
    Button mf_button = (Button) findViewById(R.id.f_button);
    switch(j) {
        case '0':
            mc_button.setBackgroundResource(R.color.game2_c_on);
            //mCMediaPlayer = MediaPlayer.create(Game2PlayActivity.this, R.raw.c_sound);
            //mCMediaPlayer.start();
            //mCMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            //    @Override
            //    public void onCompletion(MediaPlayer mp) {
            //        mCMediaPlayer.release();
            //    }
            //});
            break;
        case '1':
            md_button.setBackgroundResource(R.color.game2_d_on);
            //mDMediaPlayer = MediaPlayer.create(Game2PlayActivity.this, R.raw.d_sound);
            //mDMediaPlayer.start();
            //mDMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            //    @Override
            //    public void onCompletion(MediaPlayer mp) {
            //        mDMediaPlayer.release();
            //    }
            //});
            break;
        case '2':
            me_button.setBackgroundResource(R.color.game2_e_on);
            //mEMediaPlayer = MediaPlayer.create(Game2PlayActivity.this, R.raw.e_sound);
            //mEMediaPlayer.start();
            //mEMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            //    @Override
            //    public void onCompletion(MediaPlayer mp) {
            //        mEMediaPlayer.release();
            //    }
            //});
            break;
        case '3':
            mf_button.setBackgroundResource(R.color.game2_f_on);
            //mFMediaPlayer = MediaPlayer.create(Game2PlayActivity.this, R.raw.f_sound);
            //mFMediaPlayer.start();
            //mFMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            //    @Override
            //    public void onCompletion(MediaPlayer mp) {
            //        mFMediaPlayer.release();
            //    }
            //});
            break;
    }
}

音频播放被评论,但过去工作得很好。这实际上是关于那些 SetBackgroundResource 调用的全部内容,它们不会立即执行,而只会在 CreateSequence 方法中的 for 循环结束时执行。

如果有人想在 Android Studio 中实现整个项目(不推荐,因为它可能有很多 bug),这里是 (25 MB):http://www.mediafire.com/file/2c86sbe3rkb231d/AudiogamesSuite.zip

提前致谢

----------------------------------------------- --------------------------------

编辑 - 感谢 Martin Pfeffer 和一些谷歌搜索,设法解决了这个问题。这是更新的代码

private void createSequence(final int i) {
        Thread t = new Thread(new Runnable() {
            public void run() {
                Random rand = new Random();
                for (int j = 0; j < i; j++) {
                    final int seed = rand.nextInt(4);
                    try {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                temp.add(seed);
                                playButton(seed);
                            }
                        });
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t.setDaemon(true);
        t.start();
    }

【问题讨论】:

  • 为什么不直接使用switch(i)
  • 我不能使用整数作为参数,我认为这是解决它的最简单方法:)
  • 你只需要说 case 1 而不是 case '1'
  • 应该在我的编程课上多加注意。谢谢大佬!

标签: java android xml android-layout


【解决方案1】:

synchronized 说明符添加到方法中。

private synchronized void createSequence(int i) {
        // allow only one thread to be executed
}

编辑:

刚刚看到你不使用单独的线程。所以运行这段代码来获得延迟:

new Handler().postDelayed(new Runnable(){
        public void run() {
          // do stuff             
      }}, 1000 * DELAY_IN_SECONDS);

编辑2:

我想你正在寻找这样的东西:

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.TextView;

import java.util.concurrent.Callable;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new MyThread((TextView) findViewById(R.id.textView)).start();

    }


    class MyThread extends Thread implements Runnable {

        TextView textView;

        MyThread(TextView textView) {
            this.textView = textView;
        }

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                runOnMainUiThread(new Callable() {
                    @Override
                    public Object call() throws Exception {
                        textView.setText("" + System.currentTimeMillis());
                        return null;
                    }
                });

            }
        }

        void runOnMainUiThread(final Callable callable) {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    try {
                        callable.call();
                    } catch (Exception e) {
                        Log.e("MyThread", "runOnMainUiThread: ", e);
                    }
                }
            });
        }
    }
}

如果你有任何问题,请随时问:)

【讨论】:

  • 我已经阅读了一些关于处理程序的信息,似乎问题出在我的 Thread.sleep 调用中,而处理程序应该能够规避这个问题,对吧?无论如何,感谢您的 sn-p,我会尽快对其进行测试并通知您!
  • 不行……要不要把sn-p放到createSequence函数里?
  • 我无法理解如何准确地实现第二次编辑...??我应该在 createSequence 方法的 for 循环中创建一个新线程吗?
猜你喜欢
  • 2017-07-28
  • 1970-01-01
  • 1970-01-01
  • 2019-06-07
  • 2015-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多