Java Android-带有自定义游标适配器的Listview,运行asynctask时会崩溃
我试图做的是使用自定义游标适配器,以选择要显示的布局,并填充视图项,如TextView和ImageView 现在不是所有的listview项目中都会有图像 我的游标适配器代码是-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
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
。它看起来像是两件事之一——要么图像太大,要么内存泄漏(或者两者兼而有之)
我的建议是使用几个库中的一个来加载背景图像。以下是几点建议:
ListView
中有多少项?它是一个显示数据库输入的ListView-因此ListView项的数量是无限的,就好像它显示了当前DB行的数量一样。顺便说一句,我正试图弄明白如何使用缩略图代码——我肯定会被困在理解一两件事上,对于一个格式良好、包含所有必需信息的问题+1。