【问题标题】:Why are images that are resized asynchronously initially too large when displayed in a ListView?为什么最初异步调整大小的图像在 ListView 中显示时太大?
【发布时间】:2015-01-08 00:21:52
【问题描述】:

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

我首先尝试在GetDataCallbackdone 部分调整图像大小并看到大图。接下来,我自己实现了线程,结果相同:图像的第一屏最初显示不正确,但当它们离开屏幕并返回时修复。

作为测试,我接下来尝试直接获取数据(不是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
        }

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

【问题讨论】:

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


    【解决方案1】:

    原来问题在于适配器没有收到数据已更改的通知。因此,当 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();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-12-23
      • 1970-01-01
      • 2022-07-29
      • 1970-01-01
      • 2019-03-21
      • 1970-01-01
      • 1970-01-01
      • 2017-06-21
      • 1970-01-01
      相关资源
      最近更新 更多