下载的位图图像显示太小

Downloaded bitmap images display too small

我有一个带有自定义适配器的 ListView。每行都有一个 Pokémon 精灵,我将其下载到位图,精灵始终为 96 x 96。我手动下载了一个虚拟图像并将其放入我的 drawables 文件夹中,它呈现得很好: How it should be

但是当我实际以编程方式下载图像时,它给了我这个结果: How it is

怎么突然变小了?当我 sysout 下载的位图的高度和宽度时,它显示为 96 x 96,但它显然不会呈现为 96 x 96。

这是下载图片的任务代码

private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {

    @Override
    protected Bitmap doInBackground(String... urls) {
        String urldisplay = urls[0];
        Bitmap bm = null;
        try {
            InputStream in = new java.net.URL(urldisplay).openStream();
            bm = BitmapFactory.decodeStream(in);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bm;
    }

}

我如何调用任务

try {
        Bitmap bm = new DownloadImageTask().execute(dataModel.getSpriteUrl()).get();
        viewHolder.sprite.setImageBitmap(bm);
    } catch (Exception e) {
        e.printStackTrace();
    }

宠物小精灵行XML

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="8dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/img_sprite"
            android:layout_width="96dp"
            android:layout_height="96dp"
            android:scaleType="fitCenter" />

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="left|center_vertical"
            android:orientation="vertical">

            <TextView
                android:id="@+id/text_name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="@android:color/black"
                android:textSize="20sp"
                android:textStyle="bold" />

            <TextView
                android:id="@+id/text_cp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="18sp" />

            <TextView
                android:id="@+id/text_gendershiny"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="18sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="end"
            android:orientation="vertical">

            <Button
                android:id="@+id/btn_delete"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:backgroundTint="@color/colorPrimary"
                android:text="DELETE"
                android:textColor="#ffffff"
                android:textSize="16sp"
                android:textStyle="bold" />
        </LinearLayout>

    </LinearLayout>

</android.support.v7.widget.CardView>

使用AsyncTask 下载图片并不常见。通常这是通过名为 Glide 的库完成的。它在后台线程中下载图像并缓存它。您还可以在那里设置图像的 ScaleType。

您可能想看看这个网站。我提供了一些有关如何将 scaleType 属性与 ImageView:

一起使用的有用提示

https://robots.thoughtbot.com/android-imageview-scaletype-a-visual-guide


请参阅此答案底部的编辑内容。


现在讨论使用 AsyncTask

get() 方法的问题

使用 interface 让您知道 AsyncTask 何时完成:

public interface BitmapLoaderListener {

    void onCompletedBitmapLoaded(Bitmap bm);
}

您的 AsyncTask 可能如下所示:

public class BitmapLoader extends AsyncTask<String, Integer, Bitmap> {

    private static final String TAG = BitmapLoader.class.getSimpleName();

    private BitmapLoaderListener mListener;
    private String imageUrl = "";


    public BitmapLoader(String imageUrl, BitmapLoaderListener listener){
        this.imageUrl = imageUrl;
        this.mListener = listener;
        this.selectedSource = source;
    }


    @Override
    protected Bitmap doInBackground(String... params) {
        Bitmap bm = null;

        try{
            // Your code here !!!
        }
        catch (Exception ex){
            Log.e(TAG, ex.getMessage());
        }

        return bm;
    }

    protected void onPostExecute(Bitmap bm) {
        mListener.onCompletedBitmapLoaded(bm);
    }
}

onBindViewHolder 中调用 RecyclerView 中的 AsyncTask:

@Override
public void onBindViewHolder(final MyViewHolder holder, final int position){
    MyData data = mData.get(position);

    // Add whatever code you need here

    BitmapLoaderListener listener = new BitmapLoaderListener() {
        @Override
        public void onCompletedBitmapLoaded(Bitmap bm) {
            if (bm == null) return;
            holder.myImageView.setImageBitmap(bm);
        }
    };

    BitmapLoader loader = new BitmapLoader(imageUrl, listener);
    loader.execute();
}



您可以实现一个缓存类型系统,将图像保存到设备存储中,并仅在需要时从 Internet 加载它们。我用我的很多应用程序来做到这一点。这是可能的,但它需要处理线程和资源的经验......正如 Angelina 指出的那样,您始终可以使用 Glide 或 Picasso 库。尽管在这种情况下我很少使用第三方库,但您可能需要考虑一下——它们是设计良好且维护良好的库。



编辑:

对每个下载的图像使用缩放方法createScaledBitmap()似乎有点重。

您可能希望对布局文件进行以下简单更改:

<ImageView
   android:id="@+id/img_sprite"
   android:layout_width="96dp"
   android:layout_height="96dp" 
   android:scaleType="fitCenter"/>

有很多方法可以通过对布局文件进行一些更改来实现您想要的结果。关于您正在下载的图像大小 (96x96),我只选择最简单的。

此示例获取图像并将其强制为 ImageView 96dpx96dp,以便图像居中并缩放以适应视图边界,保持原始纵横比。

与对每个图像使用 createScaledBitmap() 方法相比,这更容易维护和修改,而且重量轻得多——不管它是否需要,哎哟!