Android:GridView与图像,如何设置动态大小和提高性能

时间:2013-05-11 11:25:50

标签: android image gallery adapter

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

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

    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支持。非常感谢帮助!

    getView方法:

    @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;
    } 
    

    ViewHolder:

    class ViewHolder {
        ImageView imageView;
    }
    

    cell_image:

    <?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>
    

1 个答案:

答案 0 :(得分: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
所以我不会在这里详细说明。