使用处理程序循环遍历数据

Using Handlers to loop through data

我正在尝试开发一种方法,该方法将循环遍历字符串变量并根据每个字符更改背景颜色,延迟一秒,以便用户可以观察到每种颜色。我研究过类似的问题,大多数答案都推荐 Handlers() 或 Timers(),因为不建议休眠 UI 线程。

我遇到的问题是 Handler 方法和 Timer 方法都创建了 Runnables 或 TimerTasks,并且我无法在不将循环迭代器声明为最终变量的情况下发送它的 int 值,这阻止了我从递增到字符串的下一个字母。

public void replayPattern(View view){
        int i=0;
        String temp;
        int delay = 1000;
        RelativeLayout myGameLayout = (RelativeLayout) findViewById(R.id.game_RelativeLayout);
        TextView display = (TextView) findViewById(R.id.display);

        display.setText("Replaying the pattern...");
        myGameLayout.setBackgroundColor(this.getResources().getColor(R.color.white));

        while(i < pattern.length()){
            temp = pattern.substring(i, i+1);

            if(temp.equals("r")){
                //Toast.makeText(getApplicationContext(), temp, Toast.LENGTH_SHORT).show();
                myGameLayout.setBackgroundColor(this.getResources().getColor(R.color.game_red));
            }
            else if(temp.equals("b")){
                //Toast.makeText(getApplicationContext(), temp, Toast.LENGTH_SHORT).show();
                myGameLayout.setBackgroundColor(this.getResources().getColor(R.color.game_blue));

            }
            else if(temp.equals("y")){
                //Toast.makeText(getApplicationContext(), temp, Toast.LENGTH_SHORT).show();
                myGameLayout.setBackgroundColor(this.getResources().getColor(R.color.game_yellow));

            }
            else{
                // error, should not occur
                myGameLayout.setBackgroundColor(this.getResources().getColor(R.color.white));
                Toast.makeText(getApplicationContext(), "Error, character not recognized: " + temp, Toast.LENGTH_SHORT).show();
            }
            i++;
            // WAIT 1 SECOND, SO USER CAN OBSERVE COLOR PATTERN
        }
        myGameLayout.setBackgroundColor(this.getResources().getColor(R.color.white));
        display.setText("");
    }

我能找到的最受欢迎的答案出现在此处 (How to call a method after a delay in Android),我已尝试在下面实施:

public void replayPattern2(View view){

        int i=0;
        //String temp;
        int delay = 1000;
        //RelativeLayout myGameLayout = (RelativeLayout) findViewById(R.id.game_RelativeLayout);
        //TextView display = (TextView) findViewById(R.id.display);

        display.setText("Replaying the pattern...");
        myGameLayout.setBackgroundColor(this.getResources().getColor(R.color.white));

        final Handler handler = new Handler();
        patternIndex = 0;

        while(patternIndex < pattern.length()-1){
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    runCount++;
                    String temp = pattern.substring(patternIndex, patternIndex+1);

                    if(temp.equals("r")){
                        Toast.makeText(getApplicationContext(), temp, Toast.LENGTH_SHORT).show();
                        myGameLayout.setBackgroundColor(getResources().getColor(R.color.game_red));
                    }
                    else if(temp.equals("b")){
                        Toast.makeText(getApplicationContext(), temp, Toast.LENGTH_SHORT).show();
                        myGameLayout.setBackgroundColor(getResources().getColor(R.color.game_blue));
                    }
                    else if(temp.equals("y")){
                        Toast.makeText(getApplicationContext(), temp, Toast.LENGTH_SHORT).show();
                        myGameLayout.setBackgroundColor(getResources().getColor(R.color.game_yellow));
                    }
                    else{
                        // error, should not occur
                        myGameLayout.setBackgroundColor(getResources().getColor(R.color.green));
                        Toast.makeText(getApplicationContext(), "Error, character not recognized: " + temp, Toast.LENGTH_SHORT).show();
                    }
                }
            }, delay);
            patternIndex++;
        }
        //myGameLayout.setBackgroundColor(this.getResources().getColor(R.color.white));
        display.setText("runcount = " + runCount);

    }

据我观察,代码实际上经过了正确数量的循环,但它实际上仍然没有在迭代之间暂停并显示中间颜色变化。可能有一些我遗漏的东西,但我已经花了将近 12 个小时来调试和研究这个中间循环延迟。任何帮助将不胜感激!

你的 replayPattern2() 函数不工作的原因是即使你 post Runnable 有延迟,在移动之前你的 for 循环没有任何延迟到下一个字符并 post 进入下一个 Runnable,因此您最终会在程序开始 1000 毫秒后将所有 Runnables 安排到一个接一个 运行。

您可以修改 Runnable,使其 运行s 然后 posts 自己回到 Handler 并在完成时延迟,检查String 结束。一开始你只需要post一个Runnable,这样你就可以摆脱for循环:

final int delay = 1000; // delay needs to be declared final to access it inside the Runnable

final Handler handler = new Handler();
patternIndex = 0;

handler.postDelayed(new Runnable() {
    @Override
    public void run() {
        runCount++;
        String temp = pattern.substring(patternIndex, patternIndex+1);

        if(temp.equals("r")){
            Toast.makeText(getApplicationContext(), temp, Toast.LENGTH_SHORT).show();
            myGameLayout.setBackgroundColor(getResources().getColor(R.color.game_red));
        }
        else if(temp.equals("b")){
            Toast.makeText(getApplicationContext(), temp, Toast.LENGTH_SHORT).show();
            myGameLayout.setBackgroundColor(getResources().getColor(R.color.game_blue));
        }
        else if(temp.equals("y")){
            Toast.makeText(getApplicationContext(), temp, Toast.LENGTH_SHORT).show();
            myGameLayout.setBackgroundColor(getResources().getColor(R.color.game_yellow));
        }
        else{
            // error, should not occur
            myGameLayout.setBackgroundColor(getResources().getColor(R.color.green));
            Toast.makeText(getApplicationContext(), "Error, character not recognized: " + temp, Toast.LENGTH_SHORT).show();
        }
        patternIndex++;
        if(patternIndex <= pattern.length()-1)
            handler.postDelayed(this, delay); // the Runnable posts itself to the Handler if not at the end of the string yet
    }

}, delay);