Android自定义SimpleCrsorAdapter,带有数据库中路径文件中的图像

Android自定义SimpleCrsorAdapter,带有数据库中路径文件中的图像,android,image,data-binding,android-cursoradapter,Android,Image,Data Binding,Android Cursoradapter,要点:自定义适配器通过数据库中的文件路径间接获取文件资源。低效率/内存问题。我需要你的意见 所有搜索、相关链接和对主题有用的内容的参考都在文章底部 下面的代码有效,但有几个因素值得关注。需要一些更有经验的眼睛在这方面,请建议改进或潜在的错误,以避免。应用不需要是内容提供商(数据来源仅限于应用本地)。讨论中的ListView将非常轻,只有大约5到最多10个条目。(我省略了数据库的内容,因为它可以工作。) 概述: 数据库包含一些文本和图像文件路径。-嗯 图像文件存储在设备上(SD卡/外部存储器,如

要点:自定义适配器通过数据库中的文件路径间接获取文件资源。低效率/内存问题。我需要你的意见

所有搜索、相关链接和对主题有用的内容的参考都在文章底部

下面的代码有效,但有几个因素值得关注。需要一些更有经验的眼睛在这方面,请建议改进或潜在的错误,以避免。应用不需要是内容提供商(数据来源仅限于应用本地)。讨论中的ListView将非常轻,只有大约5到最多10个条目。(我省略了数据库的内容,因为它可以工作。)

概述:

  • 数据库包含一些文本和图像文件路径。-嗯
  • 图像文件存储在设备上(SD卡/外部存储器,如有)。-嗯
这些文件不在数据库中,这与普通的SimpleCorsOrAdapter不同——必须提取图像文件。增加了在填充listview之前将其制作成缩略图的开销

如前所述,它很轻,但是,即使只有一个或两个条目,VM也会打嗝。我怀疑这是所有与位图相关的内存抖动:

08-27 19:53:14.273: I/dalvikvm-heap(11900): Grow heap (frag case) to 4.075MB for 1228816-byte allocation
08-27 19:53:14.393: D/dalvikvm(11900): GC_CONCURRENT freed <1K, 5% free 4032K/4244K, paused 13ms+3ms, total 116ms
[编辑-添加链接] 搜索条件: " Android自定义SimpleCrsorAdapter,带有数据库中路径文件中的图像 "

最近的命中,但尝试从res而不是外部/sd存储中提取图像(未应答):

还有一个接近命中/未命中-类似算法(未回答)参考文献4):

差不多,但OP的代码不起作用(没有有效答案):

为OP工作,但使用JSON进行远程检索,而不是本地检索(也许这可以调整,但我不清楚如何调整)。

不完全正确,但再次接近:

图像加载程序问题(参考文献2):

相关链接:

  @Override
public View newView(Context ctx, Cursor cursor, ViewGroup parent) {
    View vView = mLayoutInflater.inflate(layout, parent, false);
    vView.setTag( new ViewHolder(vView) );
    // no need to bind data here. you do in later
    return vView;// **EDITED:**need to return the view
}

点击次数名称类似,但与我的特定问题无关-这些通常指应用程序内资源:

外部引用:

  @Override
public View newView(Context ctx, Cursor cursor, ViewGroup parent) {
    View vView = mLayoutInflater.inflate(layout, parent, false);
    vView.setTag( new ViewHolder(vView) );
    // no need to bind data here. you do in later
    return vView;// **EDITED:**need to return the view
}
0)自定义光标适配器的简单介绍

1) 罗曼盖-基本布局。。。2个TXT,1个图像

2) AQuery(Android查询)

3) Android缩略图

4) 卡斯特。具有“开/关”星形图像的listview: 你可以做两件事:

1) 使用ViewHolder模式,缓存LayoutInfalter,最重要的是:不要绑定数据两次:

/* ... imports */

import static android.media.ThumbnailUtils.extractThumbnail;

public class TextAndImageCursorAdapter extends SimpleCursorAdapter { 

    private LayoutInflater mLayoutInflater;
    private Context context;
    private int layout;


    private class ViewHolder {
        TextView textView;
        ImageView imageView;

        ViewHolder(View v) {
            textView = (TextView) v.findViewById(R.id.gui_text);
            imageView = (ImageView) v.findViewById(R.id.gui_image);
        }
    }

    public TextAndImageCursorAdapter (Context ctx, int layout, Cursor c, String[] from, int[] to) {
        super(ctx, layout, c, from, to);
        this.context = ctx;
        this.layout = layout;
        mLayoutInflater = LayoutInflater.from(ctx);
    }


    @Override
    public View newView(Context ctx, Cursor cursor, ViewGroup parent) {
        View vView = mLayoutInflater.inflate(layout, parent, false);
        vView.setTag( new ViewHolder(vView) );
        // no need to bind data here. you do in later
        return vView;// **EDITED:**need to return the view
    }

    @Override
    public void bindView(View v, Context ctx, Cursor c) {
        // you might want to cache these too
        int iCol_Text = c.getColumnIndex(DBCOL_TEXT);
        int iCol_Image = c.getColumnIndex(DBCOL_IMAGE);

        String sText = c.getString(iCol_Text);
        String sFileAndPath_Image = c.getString (iCol_Image);  //// path & file

        ViewHolder vh = (ViewHolder) v.getTag();

        vh.textView.setText(sSomeText);
        vh.imageView.setImageBitmap ( mySetImage ( sFileAndPath_Image ) );
    }
}
2) 这一点非常重要:不要在每个绑定上创建缩略图。您需要缓存结果:

private void setThumbnail(String path, Bitmap b) {
    // save thumbnail to some kind of cache
    // see comment below
}

private Bitmap getThumbnail(String path) {
    Bitmap thumbnail = null;
    // try to fetch the thumbnail from some kind of cache
    // see comment below
    return thumbnail;
}

protected Bitmap mySetImage ( String path ) {
    int width = 60; int height = 40 ;

    Bitmap thumbnail = getThumbnail(path); // try to fetch thumbnail
    if (thumbnail != null) return thumbnail;

    File imgFile = new File ( path );  //// usually like: /sdcard/wherever/filename1234.bmp
    Bitmap myBitmap = null;

    if( imgFile.exists() ) {
            myBitmap = BitmapFactory.decodeFile ( imgFile.getAbsolutePath () );                  
    } else {
            Log.d ("oops", "no image file ... using default.");
            myBitmap = getTheDefaultImage ();  //// not shown - this is arbitrary
    }

    imgFile.close();
    thumbnail = extractThumbnail ( myBitmap, width, height );
    myBitmap.recycle();
    setThumbnail(path, thumbnail); // save thumbnail for later reuse
    return thumbnail;
}     
根据您的用例,您希望使用某种LruCache填充
getThumbnail()
setThumbnail()

  • android API和支持库中提供了内存中的LruCache:
  • 杰克做了一个持久的磁盘备份:
编辑:

  @Override
public View newView(Context ctx, Cursor cursor, ViewGroup parent) {
    View vView = mLayoutInflater.inflate(layout, parent, false);
    vView.setTag( new ViewHolder(vView) );
    // no need to bind data here. you do in later
    return vView;// **EDITED:**need to return the view
}
你可以做两件事:

1) 使用ViewHolder模式,缓存LayoutInfalter,最重要的是:不要绑定数据两次:

/* ... imports */

import static android.media.ThumbnailUtils.extractThumbnail;

public class TextAndImageCursorAdapter extends SimpleCursorAdapter { 

    private LayoutInflater mLayoutInflater;
    private Context context;
    private int layout;


    private class ViewHolder {
        TextView textView;
        ImageView imageView;

        ViewHolder(View v) {
            textView = (TextView) v.findViewById(R.id.gui_text);
            imageView = (ImageView) v.findViewById(R.id.gui_image);
        }
    }

    public TextAndImageCursorAdapter (Context ctx, int layout, Cursor c, String[] from, int[] to) {
        super(ctx, layout, c, from, to);
        this.context = ctx;
        this.layout = layout;
        mLayoutInflater = LayoutInflater.from(ctx);
    }


    @Override
    public View newView(Context ctx, Cursor cursor, ViewGroup parent) {
        View vView = mLayoutInflater.inflate(layout, parent, false);
        vView.setTag( new ViewHolder(vView) );
        // no need to bind data here. you do in later
        return vView;// **EDITED:**need to return the view
    }

    @Override
    public void bindView(View v, Context ctx, Cursor c) {
        // you might want to cache these too
        int iCol_Text = c.getColumnIndex(DBCOL_TEXT);
        int iCol_Image = c.getColumnIndex(DBCOL_IMAGE);

        String sText = c.getString(iCol_Text);
        String sFileAndPath_Image = c.getString (iCol_Image);  //// path & file

        ViewHolder vh = (ViewHolder) v.getTag();

        vh.textView.setText(sSomeText);
        vh.imageView.setImageBitmap ( mySetImage ( sFileAndPath_Image ) );
    }
}
2) 这一点非常重要:不要在每个绑定上创建缩略图。您需要缓存结果:

private void setThumbnail(String path, Bitmap b) {
    // save thumbnail to some kind of cache
    // see comment below
}

private Bitmap getThumbnail(String path) {
    Bitmap thumbnail = null;
    // try to fetch the thumbnail from some kind of cache
    // see comment below
    return thumbnail;
}

protected Bitmap mySetImage ( String path ) {
    int width = 60; int height = 40 ;

    Bitmap thumbnail = getThumbnail(path); // try to fetch thumbnail
    if (thumbnail != null) return thumbnail;

    File imgFile = new File ( path );  //// usually like: /sdcard/wherever/filename1234.bmp
    Bitmap myBitmap = null;

    if( imgFile.exists() ) {
            myBitmap = BitmapFactory.decodeFile ( imgFile.getAbsolutePath () );                  
    } else {
            Log.d ("oops", "no image file ... using default.");
            myBitmap = getTheDefaultImage ();  //// not shown - this is arbitrary
    }

    imgFile.close();
    thumbnail = extractThumbnail ( myBitmap, width, height );
    myBitmap.recycle();
    setThumbnail(path, thumbnail); // save thumbnail for later reuse
    return thumbnail;
}     
根据您的用例,您希望使用某种LruCache填充
getThumbnail()
setThumbnail()

  • android API和支持库中提供了内存中的LruCache:
  • 杰克做了一个持久的磁盘备份:
编辑:

  @Override
public View newView(Context ctx, Cursor cursor, ViewGroup parent) {
    View vView = mLayoutInflater.inflate(layout, parent, false);
    vView.setTag( new ViewHolder(vView) );
    // no need to bind data here. you do in later
    return vView;// **EDITED:**need to return the view
}

thx!-我在复习。。。这里有一个关于ViewHolder模式的相关链接:(来自佛罗里达州的viele Grusse an Hamburg:))澄清newView()和bindView()之间的区别:(答案有很好的解释。)事实上,我现在住在斯里兰卡;)别忘了:@DiogoBento-是的,谢谢!在使用ListView(或通常的视图)时,我不清楚调用Bitmap.recycle()的位置和时间。视图只是指向位图,还是位图实际复制到视图中?(后者似乎是浪费。)@flx-斯里兰卡?!谢尔·肖恩!thx!-我在复习。。。这里有一个关于ViewHolder模式的相关链接:(来自佛罗里达州的viele Grusse an Hamburg:))澄清newView()和bindView()之间的区别:(答案有很好的解释。)事实上,我现在住在斯里兰卡;)别忘了:@DiogoBento-是的,谢谢!在使用ListView(或通常的视图)时,我不清楚调用Bitmap.recycle()的位置和时间。视图只是指向位图,还是位图实际复制到视图中?(后者似乎是浪费。)@flx-斯里兰卡?!谢尔·肖恩!