为什么在ListView中显示时异步调整大小的图像最初太大?

时间:2015-01-08 00:21:53

标签: bitmap android-asynctask parse-platform android-imageview image-resizing

我正在从parse.com下载Parse数据字段并异步调整每个中包含的图像的大小。当视图膨胀时,图像的第一页不会调整大小。视图被回收后,它们会正确显示。

我首先尝试调整done GetDataCallback部分中的图片大小并看到了大图片。接下来,我使用相同的结果自己实现了线程:第一个图像屏幕最初显示不正确,但是当它们离开屏幕并返回时固定。

作为测试,我接下来尝试直接获取数据(不是getDataInBackground)并调整大小并且工作正常,但显然处理时间增加了。我认为该问题与此测试引起的线程有关。

一些代码:

            @Override
            public void done(List<Listing> listingList, ParseException e) {
                /* scale and save the image back to parse object */
                final float scale = getResources().getDisplayMetrics().density;
                if (e == null) {
                    Log.d("listing", "Retrieved " + listingList.size() + " listings");
                    /* clear adapter before populating */
                    adapter.clear();
                    /* iterate through listings and create listing objects */
                    for (Listing listingObject : listingList) {
                        //listingObject.resizeImage(scale);
                        new ResizeImages().execute(listingObject);
                        listings.add(listingObject);
                    }
                }
                else {
                    Log.d("listing", "Error: " + e.getMessage());
                }
            }
        });

异步调整大小:

private class ResizeImages extends AsyncTask<Listing, Void, Listing> {
    protected Listing doInBackground(Listing... params) {
        Listing listing = params[0];

        final float scale = getResources().getDisplayMetrics().density;
        try {
            byte[] data = listing.getFile().getData();
        /* Decode the byte array into BitMap to be displayed on device */
            Bitmap bitmap = BitmapFactory
                    .decodeByteArray(
                            data, 0,
                            data.length);

                /* scale image and put back into parse object */
            if (scale <= 1.0) {
                bitmap = Bitmap.createScaledBitmap(bitmap, 134, 134, false);
            } else if (scale <= 1.5) {
                bitmap = Bitmap.createScaledBitmap(bitmap, 200, 200, false);
            } 

            ...

            /* put image back into byte data and put back in "this" */
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
            byte[] scaledData = stream.toByteArray();
            bitmap.recycle();

            Log.d("Resizer", "Image resized.");
            ParseFile photoFile = new ParseFile("image.jpeg", scaledData);
            listing.setFile(photoFile);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return listing;
    }

    protected void onPostExecute(Listing listing) {
        Log.d("Resizer: ", "Resizing done");

    }
}

修改

我的修复涉及将`onPostExecute'更改为:

 protected void onPostExecute(Listing listing) {
            Log.d("Resizer: ", "Resizing done");
            listings.add(listing);          // this line from UI thread moved here
            adapter.notifyDataSetChanged(); // this line was new
        }

我在下面的答案中提供了一种更通用的异步调整位图大小的方法。

1 个答案:

答案 0 :(得分:0)

原来问题是,未通知适配器数据已更改。因此,当ListView拉出前几张图片时,它们就是原始尺寸的图片。为了使这个更通用,并希望将来帮助某人,这里是如何异步调整位图的大小:

// in your UI thread
new ResizeImages().execute(mBitmap);

// in your class
private class ResizeImages extends AsyncTask<Bitmap, Void, Listing> {
    protected Listing doInBackground(Bitmap... params) {
        Bitmap bitmap = params[0]; // grab the first bitmap.. could grab more and 
                                   // do multiple per thread
        try {  
            /* scale image however you wish. here we scale to 200x200 px */
            bitmap = Bitmap.createScaledBitmap(bitmap, 200, 200, false);

            /* put image back into byte data if you need to */
            //ByteArrayOutputStream stream = new ByteArrayOutputStream();
            //bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
            //byte[] scaledData = stream.toByteArray();

            /* put data back into bitmap if you need to */
            //Bitmap scaledBitmap = BitmapFactory
            //  .decodeByteArray(
            //           scaledData, 0,
            //           scaledData.length);

            /* recycle unneeded bitmap */
            bitmap.recycle();

            Log.d("Resizer", "Image resized.");

        } catch (ParseException e) {
            e.printStackTrace();
    }

    protected void onPostExecute(Bitmap bitmap) {
                Log.d("Resizer: ", "Resizing done");
                resizedBitmap = bitmap; // save resized bitmap into your class
                                        // variable
                bitmaps.add(bitmap); // here bitmaps is an list of bitmaps,     
                                      // like List<Listing> listingList
                /* notify adapter that the data has changed */
                adapter.notifyDataSetChanged();
    }
}