在GridView中从SD卡目录加载图像

发布于 2024-12-23 05:30:07 字数 7042 浏览 3 评论 0原文

我创建了一个应用程序,允许用户在外部存储上创建相册(文件夹)。现在我试图从所述目录中检索图像并将它们显示在 GridView 中。我使用 AsyncTask 使用 listFiles() 迭代文件目录,然后在获取每个图像后创建一个位图,回收它,然后再次使用它。我的问题是我的 GridView 中没有显示任何内容。我设置了一些日志中断,LogCat 向我显示迭代确实发生并且图像被检索。这让我认为我在将位图绑定到网格的 Adapter 类中的某个地方犯了一个错误,可能是在 getView 中?或者也许我错了。对我做错了什么有帮助吗?我尝试尽可能多地注释代码,并省略了不必要的部分。谢谢

public class AlbumGridView extends Activity implements OnItemClickListener {

private GridView sdcardImages;
private ImageAdapter imageAdapter;

private Display display;

private Bitmap bitmap;
private Bitmap b;

File[] imageList;
private static final String TAG = "AlbumGridView";
String path;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
    setContentView(R.layout.album_view);

    //display = 
    //((Object) getSystemService(Context.WINDOW_SERVICE))).getDefaultDisplay();

    path = getIntent().getStringExtra("key");
    Toast.makeText(this, path, Toast.LENGTH_SHORT).show();
    setupViews();
    setProgressBarIndeterminateVisibility(true);
    loadImages();



}

protected void onDestroy() {
    super.onDestroy();
    final GridView grid = sdcardImages;
    final int count = grid.getCount();
    ImageView v = null;
    for (int i = 0; i < count; i++) {
        v = (ImageView) grid.getChildAt(i);
        ((BitmapDrawable) v.getDrawable()).setCallback(null);
    }
}

// Set up the GridView

private void setupViews() {
    sdcardImages = (GridView) findViewById(R.id.gvAlbumView);
    // sdcardImages.setNumColumns(display.getWidth()/95);
    sdcardImages.setClipToPadding(false);
    sdcardImages.setOnItemClickListener(AlbumGridView.this);
    imageAdapter = new ImageAdapter(getApplicationContext());
    // imageAdapter.setImageList(path);
    sdcardImages.setAdapter(imageAdapter);
}

private void addImage(LoadedImage... value) {
    for (LoadedImage image : value) {
        imageAdapter.addPhoto(image);
        imageAdapter.notifyDataSetChanged();
    }
}

// Save Bitmap images to a list and return that list
@Override
public Object onRetainNonConfigurationInstance() {
    final GridView grid = sdcardImages;
    final int count = grid.getChildCount();
    final LoadedImage[] list = new LoadedImage[count];

    for (int i = 0; i < count; i++) {
        final ImageView v = (ImageView) grid.getChildAt(i);
        list[i] = new LoadedImage(
                ((BitmapDrawable) v.getDrawable()).getBitmap());
    }

    return list;
}

private void loadImages() {
    // TODO Auto-generated method stub
    final Object data = getLastNonConfigurationInstance();
    if (data == null) {
        new LoadImagesFromSDCard().execute();
    } else {
        final LoadedImage[] photos = (LoadedImage[]) data;
        if (photos.length == 0) {
            new LoadImagesFromSDCard().execute();
        }
        for (LoadedImage photo : photos) {
            addImage(photo);
        }
    }
}

public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
    // TODO Auto-generated method stub

}

/-------------------------------------------------------- ----------------------------------------------------/

//Adapter for the GridView

public class ImageAdapter extends BaseAdapter {

    private Context mContext;
    private ArrayList<LoadedImage> photos = new ArrayList<LoadedImage>();

    private String path;
    private Bitmap bitmap;

    public ImageAdapter(Context context) {
        mContext = context;
    }

    public void addPhoto(LoadedImage photo) {
        photos.add(photo);
    }

    public int getCount() {
        return photos.size();
    }

    public Object getItem(int position) {
        return photos.get(position);
    }

    public long getItemId(int position) {
        return position;
    }

    /*
     * public File[] setImageList(String path) {
     * 
     * //this.path = path; //this.imageList = imageList; //File imagesDir =
     * new File(path); //imageList = imagesDir.listFiles();
     * 
     * File imagesDir = new File(path); imageList = imagesDir.listFiles();
     * for (File image : imageList) try { bitmap =
     * BitmapFactory.decodeStream(image.toURL().openStream()); //use bitmap
     * and recycle afterwards LoadedImage lm = new LoadedImage(bitmap);
     * this.addPhoto(lm); bitmap.recycle();
     * 
     * } catch (IOException e) { e.printStackTrace(); } return imageList;
     * 
     * }
     */

    public View getView(int position, View convertView, ViewGroup parent) {
        final ImageView imageView;
        if (convertView == null) {
            imageView = new ImageView(mContext);
        } else {
            imageView = (ImageView) convertView;
        }
        imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
        imageView.setPadding(2, 2, 2, 2);
        // imageView.setImageBitmap(photos.get(position).getBitmap());
        try {
            imageView
                    .setImageBitmap(BitmapFactory
                            .decodeStream(imageList[position].toURL()
                                    .openStream()));
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return imageView;
    }
}

/*-------------------------------------------------------------------------*/

//AsyncTask to get the images

class LoadImagesFromSDCard extends AsyncTask<Object, LoadedImage, Object> {

    @Override
    protected Object doInBackground(Object... arg0) {
        // Load images from SD card in Background
        // Display each image on the screen

        File imagesDir = new File(path);
        imageList = imagesDir.listFiles();

        for (File image : imageList)

            try {

                if (bitmap != null) {
                    bitmap.recycle();
                    bitmap = null;
                }
                bitmap = BitmapFactory.decodeStream(image.toURL()
                        .openStream());
                Log.e(TAG, "Grabbed Image " + image.getName());
                // use bitmap then recycle after

                LoadedImage lm = new LoadedImage(bitmap);
                // addImage(lm);
                // imageAdapter.addPhoto(lm);
                // imageAdapter.setImageList(path);
                // imageAdapter.addPhoto(lm);
                // imageAdapter.setImageList(path);
                // bitmap.recycle();
                // addImage(lm);
                // imageAdapter.addPhoto(lm);
                Log.e(TAG, "Added Image " + lm.toString());

                // imageAdapter.setImageList(path);
                addImage(lm);

                // bitmap.recycle();

                // bitmap.recycle();

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

        return null;
    }

I've created an app that allows the user to create a photo album(Folder) on External Storage. Now I am trying to retrieve the images from said directory and display them inside a GridView. I'm using an AsyncTask to iterate through the directory of files using listFiles() and then creating a bitmap once I grab each image, recycle it, and then use it again. My problem is that nothing is showing up in my GridView. I've set up a few Log breaks and LogCat shows me that the iteration does happen and the images are retrieved. This leads me to think that I made a mistake somewhere in my Adapter class that binds the bitmaps to the Grid, possibly in getView? Or maybe I'm wrong. Any help on what I'm doing wrong? I tried to comment the code as much as possible and I've left out the unecessary pieces. Thanks

public class AlbumGridView extends Activity implements OnItemClickListener {

private GridView sdcardImages;
private ImageAdapter imageAdapter;

private Display display;

private Bitmap bitmap;
private Bitmap b;

File[] imageList;
private static final String TAG = "AlbumGridView";
String path;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
    setContentView(R.layout.album_view);

    //display = 
    //((Object) getSystemService(Context.WINDOW_SERVICE))).getDefaultDisplay();

    path = getIntent().getStringExtra("key");
    Toast.makeText(this, path, Toast.LENGTH_SHORT).show();
    setupViews();
    setProgressBarIndeterminateVisibility(true);
    loadImages();



}

protected void onDestroy() {
    super.onDestroy();
    final GridView grid = sdcardImages;
    final int count = grid.getCount();
    ImageView v = null;
    for (int i = 0; i < count; i++) {
        v = (ImageView) grid.getChildAt(i);
        ((BitmapDrawable) v.getDrawable()).setCallback(null);
    }
}

// Set up the GridView

private void setupViews() {
    sdcardImages = (GridView) findViewById(R.id.gvAlbumView);
    // sdcardImages.setNumColumns(display.getWidth()/95);
    sdcardImages.setClipToPadding(false);
    sdcardImages.setOnItemClickListener(AlbumGridView.this);
    imageAdapter = new ImageAdapter(getApplicationContext());
    // imageAdapter.setImageList(path);
    sdcardImages.setAdapter(imageAdapter);
}

private void addImage(LoadedImage... value) {
    for (LoadedImage image : value) {
        imageAdapter.addPhoto(image);
        imageAdapter.notifyDataSetChanged();
    }
}

// Save Bitmap images to a list and return that list
@Override
public Object onRetainNonConfigurationInstance() {
    final GridView grid = sdcardImages;
    final int count = grid.getChildCount();
    final LoadedImage[] list = new LoadedImage[count];

    for (int i = 0; i < count; i++) {
        final ImageView v = (ImageView) grid.getChildAt(i);
        list[i] = new LoadedImage(
                ((BitmapDrawable) v.getDrawable()).getBitmap());
    }

    return list;
}

private void loadImages() {
    // TODO Auto-generated method stub
    final Object data = getLastNonConfigurationInstance();
    if (data == null) {
        new LoadImagesFromSDCard().execute();
    } else {
        final LoadedImage[] photos = (LoadedImage[]) data;
        if (photos.length == 0) {
            new LoadImagesFromSDCard().execute();
        }
        for (LoadedImage photo : photos) {
            addImage(photo);
        }
    }
}

public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
    // TODO Auto-generated method stub

}

/-------------------------------------------------------------------------------------/

//Adapter for the GridView

public class ImageAdapter extends BaseAdapter {

    private Context mContext;
    private ArrayList<LoadedImage> photos = new ArrayList<LoadedImage>();

    private String path;
    private Bitmap bitmap;

    public ImageAdapter(Context context) {
        mContext = context;
    }

    public void addPhoto(LoadedImage photo) {
        photos.add(photo);
    }

    public int getCount() {
        return photos.size();
    }

    public Object getItem(int position) {
        return photos.get(position);
    }

    public long getItemId(int position) {
        return position;
    }

    /*
     * public File[] setImageList(String path) {
     * 
     * //this.path = path; //this.imageList = imageList; //File imagesDir =
     * new File(path); //imageList = imagesDir.listFiles();
     * 
     * File imagesDir = new File(path); imageList = imagesDir.listFiles();
     * for (File image : imageList) try { bitmap =
     * BitmapFactory.decodeStream(image.toURL().openStream()); //use bitmap
     * and recycle afterwards LoadedImage lm = new LoadedImage(bitmap);
     * this.addPhoto(lm); bitmap.recycle();
     * 
     * } catch (IOException e) { e.printStackTrace(); } return imageList;
     * 
     * }
     */

    public View getView(int position, View convertView, ViewGroup parent) {
        final ImageView imageView;
        if (convertView == null) {
            imageView = new ImageView(mContext);
        } else {
            imageView = (ImageView) convertView;
        }
        imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
        imageView.setPadding(2, 2, 2, 2);
        // imageView.setImageBitmap(photos.get(position).getBitmap());
        try {
            imageView
                    .setImageBitmap(BitmapFactory
                            .decodeStream(imageList[position].toURL()
                                    .openStream()));
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return imageView;
    }
}

/*-------------------------------------------------------------------------*/

//AsyncTask to get the images

class LoadImagesFromSDCard extends AsyncTask<Object, LoadedImage, Object> {

    @Override
    protected Object doInBackground(Object... arg0) {
        // Load images from SD card in Background
        // Display each image on the screen

        File imagesDir = new File(path);
        imageList = imagesDir.listFiles();

        for (File image : imageList)

            try {

                if (bitmap != null) {
                    bitmap.recycle();
                    bitmap = null;
                }
                bitmap = BitmapFactory.decodeStream(image.toURL()
                        .openStream());
                Log.e(TAG, "Grabbed Image " + image.getName());
                // use bitmap then recycle after

                LoadedImage lm = new LoadedImage(bitmap);
                // addImage(lm);
                // imageAdapter.addPhoto(lm);
                // imageAdapter.setImageList(path);
                // imageAdapter.addPhoto(lm);
                // imageAdapter.setImageList(path);
                // bitmap.recycle();
                // addImage(lm);
                // imageAdapter.addPhoto(lm);
                Log.e(TAG, "Added Image " + lm.toString());

                // imageAdapter.setImageList(path);
                addImage(lm);

                // bitmap.recycle();

                // bitmap.recycle();

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

        return null;
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

染墨丶若流云 2024-12-30 05:30:07

顺便说一句,这是解决方案,抱歉,花了这么长时间我才意识到其他人正在等待答案。对不起。相关代码如下。

这是 AsyncTask,它将查询设备的 MediaStore 并检索所有照片。请注意,这是检索缩略图而不是全尺寸图像,更具体地说,它是 MICRO_KIND。还有一个 Thumbnail.MINI_KIND 。

/*----------------------------ASYNC TASK TO LOAD THE     PHOTOS--------------------------------------------------------*/

public class LoadPhotos extends AsyncTask<Object, Object, Object> {

    @Override
    protected Object doInBackground(Object... params) {
        try {
            final String[] columns = { MediaStore.Images.Media._ID };
            final String orderBy = MediaStore.Images.Media._ID;

            Cursor imagecursor = managedQuery(
                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns,
                    null, null, orderBy);

            int image_column_index = imagecursor
                    .getColumnIndex(MediaStore.Images.Media._ID);

            AllPhotosActivity.count = imagecursor.getCount();
            AllPhotosActivity.windows = new Bitmap[AllPhotosActivity.count];

            for (int i = 0; i < AllPhotosActivity.count; i++) {
                imagecursor.moveToPosition(i);
                // i = index;
                int id = imagecursor.getInt(image_column_index);
                windows[i] = MediaStore.Images.Thumbnails.getThumbnail(
                        getApplicationContext().getContentResolver(), id,
                        MediaStore.Images.Thumbnails.MICRO_KIND, null);
            }

            imagecursor.close();
        } catch (Exception e) {
            e.printStackTrace();
            Log.d("AllPhotosActivity",
                    "Error occured while fetching all photos on device.");
        }
        return null;

    }

    @Override
    protected void onPostExecute(Object result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        Handler mHandler = new Handler();

        mHandler.post(new Runnable() {

            public void run() {

                pd.dismiss();
                // imageAdapter.notifyDataSetChanged();
                // sdcardImages.setAdapter(imageAdapter);

            }

        });

        // pd.dismiss();
        imagegrid.setAdapter(imageAdapter);
        // pd.dismiss();

    }

    @Override
    protected void onProgressUpdate(Object... values) {
        // TODO Auto-generated method stub
        super.onProgressUpdate(values);
    }

}

这是 GridView 的适配器,它将把缩略图绑定到 gridview。我的问题只是在 ImageAdapter 的 getView 方法中,请注意,我正在从我称为 windows 的位图数组的不同索引设置 ImageView 资源。

public class ImageAdapter extends BaseAdapter {
    private Context mContext;

    public ImageAdapter(Context c) {
        mContext = c;
    }

    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView i = (ImageView) convertView;
        if (i != null) {
            i.setImageBitmap(windows[position]);
        } else {
            i = new ImageView(mContext.getApplicationContext());
            // i.setPadding(3, 3, 3, 3);
            // i.setScaleType(ImageView.ScaleType.FIT_CENTER);
            i.setAdjustViewBounds(true);
            // i.setMaxHeight(200);
            // i.setMaxWidth(200);
            i.setPadding(3, 3, 3, 3);
            i.setLayoutParams(new GridView.LayoutParams(92, 92));
            i.setImageBitmap(windows[position]);

        }
        return i;
    }

    public int getCount() {
        // TODO Auto-generated method stub
        return count;
    }
}

Here's the solution btw, sorry It took so long to I wasn't aware that others were waiting for the answer. Sorry. The relevant code is below.

This is AsyncTask that will query the device's MediaStore and retrieve all the photos. Note that this is retrieving the thumbnails and not the full size images, and more specifically it's the MICRO_KIND. There is also a Thumbnail.MINI_KIND as well.

/*----------------------------ASYNC TASK TO LOAD THE     PHOTOS--------------------------------------------------------*/

public class LoadPhotos extends AsyncTask<Object, Object, Object> {

    @Override
    protected Object doInBackground(Object... params) {
        try {
            final String[] columns = { MediaStore.Images.Media._ID };
            final String orderBy = MediaStore.Images.Media._ID;

            Cursor imagecursor = managedQuery(
                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns,
                    null, null, orderBy);

            int image_column_index = imagecursor
                    .getColumnIndex(MediaStore.Images.Media._ID);

            AllPhotosActivity.count = imagecursor.getCount();
            AllPhotosActivity.windows = new Bitmap[AllPhotosActivity.count];

            for (int i = 0; i < AllPhotosActivity.count; i++) {
                imagecursor.moveToPosition(i);
                // i = index;
                int id = imagecursor.getInt(image_column_index);
                windows[i] = MediaStore.Images.Thumbnails.getThumbnail(
                        getApplicationContext().getContentResolver(), id,
                        MediaStore.Images.Thumbnails.MICRO_KIND, null);
            }

            imagecursor.close();
        } catch (Exception e) {
            e.printStackTrace();
            Log.d("AllPhotosActivity",
                    "Error occured while fetching all photos on device.");
        }
        return null;

    }

    @Override
    protected void onPostExecute(Object result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        Handler mHandler = new Handler();

        mHandler.post(new Runnable() {

            public void run() {

                pd.dismiss();
                // imageAdapter.notifyDataSetChanged();
                // sdcardImages.setAdapter(imageAdapter);

            }

        });

        // pd.dismiss();
        imagegrid.setAdapter(imageAdapter);
        // pd.dismiss();

    }

    @Override
    protected void onProgressUpdate(Object... values) {
        // TODO Auto-generated method stub
        super.onProgressUpdate(values);
    }

}

Here's the adapter for the GridView that's going to bind your thumbnails to the gridview. My issue was simply in the getView method of my ImageAdapter, notice I'm setting my ImageView resources from different indexes of an array of Bitmaps I called windows.

public class ImageAdapter extends BaseAdapter {
    private Context mContext;

    public ImageAdapter(Context c) {
        mContext = c;
    }

    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView i = (ImageView) convertView;
        if (i != null) {
            i.setImageBitmap(windows[position]);
        } else {
            i = new ImageView(mContext.getApplicationContext());
            // i.setPadding(3, 3, 3, 3);
            // i.setScaleType(ImageView.ScaleType.FIT_CENTER);
            i.setAdjustViewBounds(true);
            // i.setMaxHeight(200);
            // i.setMaxWidth(200);
            i.setPadding(3, 3, 3, 3);
            i.setLayoutParams(new GridView.LayoutParams(92, 92));
            i.setImageBitmap(windows[position]);

        }
        return i;
    }

    public int getCount() {
        // TODO Auto-generated method stub
        return count;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文