AsyncTask 中的 ProgressBar 崩溃

ProgressBar in AsyncTask crashes

AsyncTask 中的 ProgressBar 导致崩溃。此代码实质上是从 URL 加载图像,并在执行此操作时显示进度微调器。该组中的第一张图片加载正常,但随后应用程序崩溃了。

public class LoadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
ProgressBar progressBar;

public LoadImageTask(ImageView bmImage, ProgressBar progressBar) {
    this.bmImage = bmImage;
    this.progressBar = progressBar;
}

protected Bitmap doInBackground(String... urls) {
    progressBar.setVisibility(View.VISIBLE);
    String urldisplay = urls[0];
    Bitmap scaledImage = null;
    try {
        InputStream in = new java.net.URL(urldisplay).openStream();
        Bitmap image = BitmapFactory.decodeStream(in);

        scaledImage = Bitmap.createScaledBitmap(image, 380, 250, false);
    } catch (Exception e) {
        Log.e("Error", e.getMessage());
        e.printStackTrace();
    }
    return scaledImage;
}

protected void onPostExecute(Bitmap result) {
    progressBar.setVisibility(View.GONE);
    bmImage.setImageBitmap(result);
}

}

控制台打印输出:

 02-03 02:45:44.014  24125-24375/simplewall.ryandushane.com.simplewall E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #5
    Process: simplewall.ryandushane.com.simplewall, PID: 24125
    java.lang.RuntimeException: An error occured while executing doInBackground()
            at android.os.AsyncTask.done(AsyncTask.java:300)
            at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
            at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
            at java.util.concurrent.FutureTask.run(FutureTask.java:242)
            at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:231)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:818)
     Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
            at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6247)
            at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:867)
            at android.view.View.requestLayout(View.java:17364)
            at android.view.View.requestLayout(View.java:17364)
            at android.view.View.requestLayout(View.java:17364)
            at android.view.View.requestLayout(View.java:17364)
            at android.view.View.requestLayout(View.java:17364)
            at android.view.View.requestLayout(View.java:17364)
            at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:360)
            at android.view.View.requestLayout(View.java:17364)
            at android.widget.AbsListView.requestLayout(AbsListView.java:1975)
            at android.view.View.requestLayout(View.java:17364)
            at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:360)
            at android.view.View.requestLayout(View.java:17364)
            at android.view.View.setFlags(View.java:9633)
            at android.view.View.setVisibility(View.java:6663)
            at android.widget.ProgressBar.setVisibility(ProgressBar.java:1563)
            at simplewall.ryandushane.com.simplewall.LoadImageTask.doInBackground(LoadImageTask.java:27)
            at simplewall.ryandushane.com.simplewall.LoadImageTask.doInBackground(LoadImageTask.java:17)
            at android.os.AsyncTask.call(AsyncTask.java:288)
            at java.util.concurrent.FutureTask.run(FutureTask.java:237)
            at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:231)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:818)

您不能在 doInBackground 中设置 progressBar.setVisibility(View.VISIBLE);。它是一个不同的线程

protected Bitmap doInBackground(String... urls) {
    runOnUiThread (new Runnable () {

                        @Override
                        public void run () {

                            progressBar.setVisibility(View.VISIBLE);

                        }
                    });

    String urldisplay = urls[0];
    Bitmap scaledImage = null;
    try {
        InputStream in = new java.net.URL(urldisplay).openStream();
        Bitmap image = BitmapFactory.decodeStream(in);

        scaledImage = Bitmap.createScaledBitmap(image, 380, 250, false);
    } catch (Exception e) {
        Log.e("Error", e.getMessage());
        e.printStackTrace();
    }
    return scaledImage;
}

CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views

因为您正在从非 ui 线程上的 doInBackground 调用 progressBar.setVisibility 方法。

覆盖 AsyncTaskonPreExecute() 方法,运行 在主 UI 线程上更改进度条的可见性:

@Override
protected void onPreExecute() {
     progressBar.setVisibility(View.VISIBLE);
}

onPreExecute

中移动progressBar.setVisibility(View.VISIBLE);

将此 progressBar.setVisibility(View.VISIBLE) 放在 AsyncTask 的 onPreExecute() 方法中,并从 doInBackground 方法中删除此行。