Android:无法在没有IndexOutOfBoundsException的for / while循环内执行Handler.postDelayed

时间:2017-01-31 21:34:58

标签: java android

我想以编程方式更改ImageView的背景,但是在单独的线程上的for / while循环中。在我的例子中,我在一个名为' lights'的ArrayList中有3560个ImageView。我希望在短暂延迟后改变循环中的每个背景,即每秒更改一次。

ArrayList<ImageView> lights = new ArrayList<>();
int numberOfLights = 3560;

我最初使用的是这段代码,但是有一个问题是&#39;我&#39;必须被声明为final,因为它是从内部类调用的,如果我需要for for循环那就不可能......

Handler h = new Handler();

for( int i = 0; i < numberOfLights; i++) {

    h.postDelayed(new Runnable() {
        @Override
        public void run() {
            lights.get(i).setBackgroundResource(R.drawable.light_white);
        }

    }, 1000);
}

因此我尝试使用全局变量:

Handler h = new Handler();
counter = 0;

for( ; counter < numberOfLights; counter++) {

    h.postDelayed(new Runnable() {
        @Override
        public void run() {
            lights.get(counter).setBackgroundResource(R.drawable.light_white);
         }

    }, 1000);
}

好像这个计数器被完全忽略了,即使计数器超过numberOfLights,h.postDelayed也会运行,我尝试使用Thread.sleep调用正常的Threads,导致只有&#39;只有创建视图层次结构的原始线程可以触及其视图&#39;并且还使用了runOnUiThread方法,但没有运气。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

对每个循环使用。它比传统循环更优雅,在这种情况下,你可以使局部变量最终

for(final ImageView light: lights) {

    h.postDelayed(new Runnable() {
        @Override
        public void run() {
            light.setBackgroundResource(R.drawable.light_white);
        }

    }, 1000);
}

另外,将处理程序定义为

Handler h = new Handler(Looper.getMainLooper());

为了在UI线程上运行代码

答案 1 :(得分:0)

只需创建一个新变量:

final int iCopy = i;

然后在Runnable中使用它。

Handler h = new Handler();

for( int i = 0; i < numberOfLights; i++) {
    final int iCopy = i;

    h.postDelayed(new Runnable() {
        @Override
        public void run() {
            lights.get(iCopy).setBackgroundResource(R.drawable.light_white);
        }

    }, 1000);
}

但是,如果同时修改lights,则可能无法避免IndexOutOfBoundsException。在这种情况下,范围检查或制作阵列或灯光的副本将解决您的问题。