1

我想做一个允许我添加或删除一些照片的图像管理器。如果可能的话,我不想使用外部库。现在我尝试为显示一些图片的 GridView 做适配,这些图片是从用户使用他的相机拍摄的,我有一些问题:

  1. 我想为每行显示 3 张图片,我该怎么做?(现在我用 imageView.setLayoutParams(layoutParams);)
  2. 性能不是很好,我该如何改进呢?因为理论上我应该放大量的图片。

这是我的适配器:

public class CustomGalleryAdapter extends BaseAdapter {

private Context context;
private List<String> resources;

// Constructor
public CustomGalleryAdapter(Context context, List<String> resources){
    super();

    this.context = context;
    this.resources = resources;
}

@Override
public int getCount() {
    return resources.size();
}

@Override
public Object getItem(int position) {
    return resources.get(position);
}

@Override
public long getItemId(int position) {
    return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    // Crea un ImageView
    ImageView imageView = new ImageView(context);

    // Carica un file dal path dato
    File imgFile = new  File(resources.get(position));

    // Se l'immagine esiste
    if(imgFile.exists()){

        // Decodifica il Bitmap
        Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());

        // Setta il bitmap
        imageView.setImageBitmap(myBitmap);
    }

    // Setta le proprietà dell'immagine
    imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
    GridView.LayoutParams layoutParams = new GridView.LayoutParams(100, 150);
    imageView.setLayoutParams(layoutParams);

    // Ritorna l'immagine
    return imageView;
} 
}

这是我的布局:

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/gridView"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_margin="20dp"
    android:numColumns="auto_fit"
    android:columnWidth="90dp"
    android:horizontalSpacing="10dp"
    android:verticalSpacing="10dp"
    android:gravity="center"
    android:stretchMode="columnWidth" > 
</GridView>

编辑:
我尝试修改,添加了 convertView 检查和 ViewHolder,但我不知道如何添加 LruCache 支持。非常感谢您的帮助!

获取视图方法:

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    ViewHolder holder;
    if (convertView == null) {

        Log.d("IMAGES","convertView = null");
        mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        holder = new ViewHolder();
        convertView = mInflater.inflate(R.layout.cell_image, null);      
        holder.imageView = (ImageView) convertView.findViewById(R.id.cellImage);   
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }           

    Log.d("IMAGES","decoding...");

    // Decodifica il Bitmap
    Bitmap myBitmap = BitmapFactory.decodeFile(resources.get(position));

    // Setta il bitmap
    holder.imageView.setImageBitmap(myBitmap);

    return convertView;
} 

视图持有者:

class ViewHolder {
    ImageView imageView;
}

细胞图像:

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/cellImage"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scaleType="centerCrop"
    android:adjustViewBounds="true" >

</ImageView>
4

1 回答 1

2
 File imgFile = new  File(resources.get(position));

    // Se l'immagine esiste
    if(imgFile.exists()){

        // Decodifica il Bitmap
        Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());

        // Setta il bitmap
        imageView.setImageBitmap(myBitmap);

这是万恶之源。好的,我在夸大其词,但这很糟糕:您正在实例化一个新文件并在每次调用 getView 时对其进行解码(并且可以多次调用它)。所以这不能带来好的表现。
为什么 ?
此代码在处理 UI 的主线程中运行。所以你不能在那里做繁重的工作,除非你想冻结 UI。对于处理视图(如 getView)的方法尤其如此,它们对 UI 至关重要。
你正在解码位图并从那里的磁盘读取。

你应该看看 list/gridView 库如何处理这个问题。您必须实现 ConvertView 和 ViewHandler 设计模式才能有效地使用 getView。
此外,您将需要实现自己的加载器,它在两个级别上处理您的文件:内存中的 lruCache,如果它们不在缓存中,则从磁盘中获取它们。
一旦这三件事得到实施,你的列表中应该会有非常流畅的表现。Android 官方开发网站上的列表视图和“高效显示位图”课程为这些主题提供了很好的起点。


编辑:关于 LruCache。最近最少使用的缓存是一个缓存,当它变得太大时会自动删除其最少使用的条目(这非常方便,不会占用太多内存)。Android 已经提供了一个,它甚至是支持库的一部分android.support.v4.util.LruCache
您想要做的不是直接读取文件并在 getView 中显示您的位图,而是调用将为您执行此操作的 ImageLoader。
加载器的实现取决于你。基本上你必须能够用图像的地址来调用它。首先它会检查它是否已经在内存中(从内存中读取比从磁盘中读取要快得多),如果它在那里,直接显示它。
如果没有,您需要在另一个线程中工作。涉及繁重计算、磁盘或网络的所有内容都需要在主线程之外进行,以保持其性能。在另一个线程(使用 AsyncTask 或 ThreadPool)中,您将从磁盘读取文件,将其放入缓存中并在主线程中显示。
官方文档已经有关于如何使用 Lrucache 的详细信息:
https
://developer.android.com/training/displaying-bitmaps/cache-bitmap.html 以及如何从主线程处理位图:
https://developer .android.com/training/displaying-bitmaps/process-bitmap.html
所以我不会在这里详述。

于 2013-05-11T11:35:41.137 回答