14

在我的 android 应用程序中,我从云端下载了一张图片。下载是在一个线程中执行的,在同一个线程中,我还使用新下载的图像设置了一个图像视图。设置图像后,我然后调用postinvalidate().

但是图像不会立即显示出来。有没有办法让重绘立即发生?我需要一种触发绘图周期的方法。

4

4 回答 4

45

从 View 类派生的每个类都有invalidate()postInvalidate()方法。如果invalidate()被调用,它会告诉系统当前视图已经改变,应该尽快重绘。由于此方法只能从您的UIThread调用,当您不在UIThread中并且仍想通知系统您的视图已更改时,需要另一个方法。该postInvalidate()方法从非 UIThread通知系统,并尽快在 UIThread 上的下一个事件循环中重绘视图。

在您的情况下,您可以在(智能后台线程)的帮助下实现您想要的AsyncTask。AsyncTask 可以正确且轻松地使用 UI 线程。此类允许在 UI 线程上执行后台操作(在您的情况下在后台下载图像)并发布结果(将您的位图设置为 ImageView),而无需操作线程和/或处理程序。

异步任务由在后台线程上运行的计算定义,其结果在 UI 线程上发布。异步任务由3 个通用类型定义,称为 Params、Progress 和 Result,以及4 个步骤,称为 begin、doInBackground、processProgress 和 end。

4个步骤

当一个异步任务被执行时,任务会经过 4 个步骤:

onPreExecute(),在任务执行后立即在 UI 线程上调用。此步骤通常用于设置任务,例如在从云下载图像之前在用户界面中显示进度条,用于提供良好的用户体验。

doInBackground(Params...),在 onPreExecute() 完成执行后立即在后台线程上调用。此步骤用于执行可能需要很长时间的后台计算。异步任务的参数传递到这一步。计算的结果必须由这一步返回,并将传递回最后一步。此步骤还可以使用 publishProgress(Progress...) 来发布一个或多个进度单元。这些值在 UI 线程上的 onProgressUpdate(Progress...) 步骤中发布。

onProgressUpdate(Progress...),在调用 后在 UI 线程上调用publishProgress(Progress...)。执行的时间是不确定的。此方法用于在后台计算仍在执行时在用户界面中显示任何形式的进度。

onPostExecute(Result),在后台计算完成后在 UI 线程上调用。背景计算的结果作为该方法中的参数传递给此步骤,您可以将位图设置为您的 imageView 并使您的视图无效

于 2012-08-10T01:43:17.197 回答
4

无效化不起作用。临时更改 uri 或 url 或图像的路径并更改回所需的路径有效。例如,如果我有

image_url="myhost/img.png";
himg.setImageURI(image_url, imageLoader);

我可以将其刷新为:

 himg.setImageURI(null, imageLoader);
 himg.setImageURI(image_url, imageLoader)
于 2016-08-03T19:56:47.207 回答
3

你试过用invalidate()吗?它强制视图立即重绘,而不是在下一个周期

于 2012-08-10T00:23:49.467 回答
0
new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (!socket.isClosed()) {
                    imgArray = receiveImagebytes();
                }
            }
        }).start();

        try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }


while (!socket.isClosed()) {
            runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub

                    imageView.setImageBitmap(BitmapFactory.decodeByteArray(imgArray, 0, imgArray.length));
                    imageView.invalidate();
                }
            });
于 2012-08-10T00:52:23.567 回答