Java Android-带有自定义游标适配器的Listview,运行asynctask时会崩溃

Java Android-带有自定义游标适配器的Listview,运行asynctask时会崩溃,java,android,listview,android-asynctask,Java,Android,Listview,Android Asynctask,我试图做的是使用自定义游标适配器,以选择要显示的布局,并填充视图项,如TextView和ImageView 现在不是所有的listview项目中都会有图像 我的游标适配器代码是- private static class ViewHolder { TextView mesg; TextView mesg2; TextView send; ImageView myImage; } public class ChatCursorAdapter extends

我试图做的是使用自定义游标适配器,以选择要显示的布局,并填充视图项,如TextView和ImageView

现在不是所有的listview项目中都会有图像

我的游标适配器代码是-

    private static class ViewHolder {
    TextView mesg;
    TextView mesg2;
    TextView send;
    ImageView myImage;
}

public class ChatCursorAdapter extends CursorAdapter implements OnClickListener {

    public ChatCursorAdapter(Context context, Cursor c) {
        super(context, c, 0);
    }

    @Override
    public int getCount() {
        return getCursor() == null ? 0 : super.getCount();
    }

    @Override
    public int getViewTypeCount() {
        return 2;
    }

    @Override
    public int getItemViewType(int _position) {

        Cursor cursor = (Cursor) getItem(_position);
        return getItemViewType(cursor);
    }

      private int getItemViewType(Cursor cursor) {

            String sender = cursor.getString(2);

                    String saveUser =   user;

                    if (saveUser.equalsIgnoreCase(sender)){

                        return 0;
                    }else{
                        return 1;
                    }

      }



    @Override
    public void bindView(View view, Context context, Cursor cursor) {

    ViewHolder holder = (ViewHolder) view.getTag();

        String msg = cursor.getString(3);
        String msg2 = cursor.getString(4);
        String sender = cursor.getString(2);

        holder.mesg.setText(getSmiledText(Main.this,msg));
        holder.mesg2.setText(getSmiledText(Main.this,msg2));
        holder.send.setText(sender);


        picPath = cursor.getString(8);


        if(picPath == null || picPath.isEmpty()){

                holder.myImage.setVisibility(View.GONE);

             }else{

              File file = new File(picPath);

              if(file.exists()){

                 new AsyncImageSetter(holder.myImage, picPath).execute();
                 holder.myImage.setOnClickListener(this);

            }



             }


    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        ViewHolder holder = new ViewHolder();
        View itemLayout = null;
        switch(getItemViewType(cursor)){
        case 0:
            itemLayout = getLayoutInflater().inflate(R.layout.msg_item1,parent, false);
            break;
        case 1:
            itemLayout =  getLayoutInflater().inflate(R.layout.msg_item13, parent,false);
            break;

        }

        itemLayout.setTag(holder);
        holder.mesg = (TextView) itemLayout.findViewById(R.id.text_start);
        holder.mesg2 = (TextView) itemLayout.findViewById(R.id.text_end);
        holder.send = (TextView) itemLayout.findViewById(R.id.text_from);
        holder.myImage = (ImageView) itemLayout.findViewById(R.id.imageView_msgpic);
        return itemLayout;

    }



}
     public class AsyncImageSetter extends AsyncTask<Void, Void, Void> {

     private ImageView img;
     private String path;
     private Bitmap bm;

         public AsyncImageSetter(ImageView img, String path) {
         this.img = img;
         this.path = path;


     }

     @Override
     protected Void doInBackground(Void... params) {

        bm = BitmapFactory.decodeFile(path);
        bm = setImageToImageView(path);

         return null;
     }

     @Override
     protected void onPostExecute(Void result) {

         img.setTag(path);
         img.setImageBitmap(bm);
         //img.setVisibility(View.VISIBLE);

         super.onPostExecute(result);
     }
正如您看到的,当需要将图像加载到ImageView时,我使用asynctask以使列表视图的滚动更加平滑

这是异步任务代码的工作方式-

    private static class ViewHolder {
    TextView mesg;
    TextView mesg2;
    TextView send;
    ImageView myImage;
}

public class ChatCursorAdapter extends CursorAdapter implements OnClickListener {

    public ChatCursorAdapter(Context context, Cursor c) {
        super(context, c, 0);
    }

    @Override
    public int getCount() {
        return getCursor() == null ? 0 : super.getCount();
    }

    @Override
    public int getViewTypeCount() {
        return 2;
    }

    @Override
    public int getItemViewType(int _position) {

        Cursor cursor = (Cursor) getItem(_position);
        return getItemViewType(cursor);
    }

      private int getItemViewType(Cursor cursor) {

            String sender = cursor.getString(2);

                    String saveUser =   user;

                    if (saveUser.equalsIgnoreCase(sender)){

                        return 0;
                    }else{
                        return 1;
                    }

      }



    @Override
    public void bindView(View view, Context context, Cursor cursor) {

    ViewHolder holder = (ViewHolder) view.getTag();

        String msg = cursor.getString(3);
        String msg2 = cursor.getString(4);
        String sender = cursor.getString(2);

        holder.mesg.setText(getSmiledText(Main.this,msg));
        holder.mesg2.setText(getSmiledText(Main.this,msg2));
        holder.send.setText(sender);


        picPath = cursor.getString(8);


        if(picPath == null || picPath.isEmpty()){

                holder.myImage.setVisibility(View.GONE);

             }else{

              File file = new File(picPath);

              if(file.exists()){

                 new AsyncImageSetter(holder.myImage, picPath).execute();
                 holder.myImage.setOnClickListener(this);

            }



             }


    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        ViewHolder holder = new ViewHolder();
        View itemLayout = null;
        switch(getItemViewType(cursor)){
        case 0:
            itemLayout = getLayoutInflater().inflate(R.layout.msg_item1,parent, false);
            break;
        case 1:
            itemLayout =  getLayoutInflater().inflate(R.layout.msg_item13, parent,false);
            break;

        }

        itemLayout.setTag(holder);
        holder.mesg = (TextView) itemLayout.findViewById(R.id.text_start);
        holder.mesg2 = (TextView) itemLayout.findViewById(R.id.text_end);
        holder.send = (TextView) itemLayout.findViewById(R.id.text_from);
        holder.myImage = (ImageView) itemLayout.findViewById(R.id.imageView_msgpic);
        return itemLayout;

    }



}
     public class AsyncImageSetter extends AsyncTask<Void, Void, Void> {

     private ImageView img;
     private String path;
     private Bitmap bm;

         public AsyncImageSetter(ImageView img, String path) {
         this.img = img;
         this.path = path;


     }

     @Override
     protected Void doInBackground(Void... params) {

        bm = BitmapFactory.decodeFile(path);
        bm = setImageToImageView(path);

         return null;
     }

     @Override
     protected void onPostExecute(Void result) {

         img.setTag(path);
         img.setImageBitmap(bm);
         //img.setVisibility(View.VISIBLE);

         super.onPostExecute(result);
     }
那么我做错了什么


感谢您提供的任何帮助

在我看来,您试图存储在内存中的
位图
太大,无法存储在平板电脑/仿真器的内存中。在这里

bm = BitmapFactory.decodeFile(path);
查看代码是否适用于比来自当前路径的文件小得多的文件(还可以查看代码是否适用于较小的列表)。这也可能是“压垮骆驼背的稻草”的一个例子。如果您当前的应用程序已经非常占用内存,那么您可能必须检查当前的代码并优化内存管理

由于您正在为
列表视图
中的每个项目创建一个
异步任务
,因此您试图同时在内存中保存那么多图像。所以你可能需要找到另一种方法来做。您可能需要尝试将图像的缩略图加载到
ImageView
s中

我希望这有帮助


示例实现
为了实现上面链接的缩略图示例,我可能会使用一种可能的方法来获取缩略图,我可以通过添加以下作为类变量(并在构造函数中实例化)来存储传递给您的
ChatCursorAdapter
的上下文

然后(如上所述),我可以使用
上下文
获取
ContentResolver
实例,并通过其构造函数将该实例传递到
异步任务
。然后,我们可以在示例代码中添加该方法,以将缩略图添加到自定义AsyncTask中,该任务可能如下所示:

ContentResolver cr;

public AsyncImageSetter(ImageView img, String path, ContentResolver cr) {
     this.img = img;
     this.path = path;
     this.cr = cr;
     }
...

@Override
 protected Void doInBackground(Void... params) {
    try{
         bm = getThumbnail(cr, path);
    }catch(Exception e){}

     return null;
 }

private Bitmap getThumbnail(ContentResolver cr, String path) throws Exception {

    Cursor ca = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[] { MediaStore.MediaColumns._ID }, MediaStore.MediaColumns.DATA + "=?", new String[] {path}, null);
    if (ca != null && ca.moveToFirst()) {
        int id = ca.getInt(ca.getColumnIndex(MediaStore.MediaColumns._ID));
        ca.close();
        return MediaStore.Images.Thumbnails.getThumbnail(cr, id, MediaStore.Images.Thumbnails.MICRO_KIND, null );
    }

    ca.close();
    return null;

}

原因在堆栈跟踪中:
java.lang.OutOfMemoryError
。它看起来像是两件事之一——要么图像太大,要么内存泄漏(或者两者兼而有之)

我的建议是使用几个库中的一个来加载背景图像。以下是几点建议:


我在移动设备(galaxy s3)上运行它,所以如果它在真实设备上不工作,它似乎是无用的。加载图像的缩略图到底是什么意思?Android会存储存储的每个图像的“缩略图”。这是每个存储图像的非常低分辨率版本。这个分辨率对于你可能看到的几乎任何东西都足够好(但是足够小,它不会消耗你所有的记忆)。我添加了一个带有示例的链接。@4这-顺便问一下,
ListView
中有多少项?它是一个显示数据库输入的ListView-因此ListView项的数量是无限的,就好像它显示了当前DB行的数量一样。顺便说一句,我正试图弄明白如何使用缩略图代码——我肯定会被困在理解一两件事上,对于一个格式良好、包含所有必需信息的问题+1。