使用 UI-Thread 更新 ImageView 的位图

Posted

技术标签:

【中文标题】使用 UI-Thread 更新 ImageView 的位图【英文标题】:Update ImageView's bitmap using UI-Thread 【发布时间】:2014-11-28 20:54:41 【问题描述】:

在另一个操作期间,我必须每隔一秒处理一次位图的像素,并在ImageView 中显示结果。这是一种操作位图并更新的方法ImageView

private void overlay(Bitmap bitmap) 
int j = 70;
while (flag) 
    //here I manipulate some pixels of bitmap that corresponds to "j" 
    //and save result in "tempBmp":
    ...
    //update imageView:
    iv1.setImageBitmap(tempBmp);
    iv1.postInvalidate();
    //          try 
    //              Thread.sleep(1000);
    //           catch (InterruptedException e) 
    //          
    //update "j":
    j = (j+1)%src.rows();


从UI线程(onclick按钮事件)调用上面的方法是这样的:

runOnUiThread(new Runnable() 
    public void run() 
        overlay(bmp);
    
);

App运行时没有问题,App crash或者ANR,但是ImageView(iv1)没有更新。我调试代码和位图的像素正在操作。我也取消了try/catch 块的注释,但结果是一样的。

很奇怪:当我评论 while 块的开始和结束时,位图操作正确(一次和j = 70)并且ImageView 按预期更新!

更新问题:

关于 eshayne 和 Onik 的 cmets 和答案,我将 overlay 方法中的像素操作更改为简单的操作并检查结果,但结果是相同的。真正的overlay 方法使用openCV 但这里我改变了像素的颜色,所以你可以在不使用openCV 的情况下看到结果:

btn.setOnClickListener(new OnClickListener() 

    @Override
    public void onClick(View arg0) 
        new Thread(new Runnable() 
            @Override
            public void run() 
                overlay(bmp);
            
        ).run();
    
);

叠加法,简化:

private void overlay(Bitmap bitmap)
    int j = 0;
    tempBmp = Bitmap.createBitmap(bitmap);
    while (j < bitmap.getHeight()) 
        for (int i = 0; i < bitmap.getWidth(); i++) 
            tempBmp.setPixel(i, j, 0);
        

        try 
            Thread.sleep(100);
         catch (InterruptedException e) 
            e.printStackTrace();
        

        // post the changes to Ui thread
        iv1.post(new Runnable() 
            @Override
            public void run() 
                iv1.setImageBitmap(tempBmp);
            
        );
        j = (j + 1);
    


如何使用while 每秒更新ImageView?我做错什么了吗?

【问题讨论】:

除了主线程我看不到任何线程 @blackbelt OK!但是为什么imageview没有更新? 我也看不到你在哪里修改位图 @blackbelt 位图在while 块中操作,在第二行之后,我添加为评论:here I manipulate some pixels of bitmap that corresponds to "j" ... 您应该在主线程之外进行所有操作,并且只使用 UI 线程来重绘位图。 【参考方案1】:

尝试将循环移到 UI 线程之外,然后在 UI 线程中运行 setImageBitmap 调用。比如:

// from non-UI thread:
while (flag) 
    // perform image manipulation
    runOnUiThread(new Runnable() 
        @Override
        public void run() 
            iv1.setImageBitmap(tempBmp);
        
    );

【讨论】:

以上是关于使用 UI-Thread 更新 ImageView 的位图的主要内容,如果未能解决你的问题,请参考以下文章

在android中经常更新ImageView

ScrollView 未使用 imageview 更新

使用Viewpager更新Fragment中的Imageview

ImageView 不更新 onActivityResult 的变化

Android:是不是可以使用数字更新 ImageView/ImageButton 以显示新消息的数量?

使用 Alamofireimage 从服务器获取图像后,Imageview 未更新