我正在开发聊天应用,我已经实施了图片发送。所以没有图像一切正常。但现在我正面临发送/接收显示图像的问题。为此我首先下载了图像并将其保存在外部存储器中。我的想法很简单,就是在imageview
方法的getView
中设置位图。获取图像和显示没有错,但列表视图遗留下来。
这是我的代码 -
ViewHolder holder = null;
if(convertView == null ){
convertView = inflater.inflate(R.layout.chat_list, null);
holder = new ViewHolder();
holder.mMsg = (TextView) convertView.findViewById(R.id.text);
holder.mDate = (TextView) convertView.findViewById(R.id.text1);
holder.mLinLay=(LinearLayout) convertView.findViewById(R.id.linSide1);
holder.mRelLay=(RelativeLayout) convertView.findViewById(R.id.relSide);
holder.img=(ImageView)convertView.findViewById(R.id.image);
holder.progCircle=(ProgressBar)convertView.findViewById(R.id.pbHeaderProgress);
convertView.setTag(holder);
} else{
holder = (ViewHolder) convertView.getTag();
}
holder.position=position;
holder.img.setTag(position+"img");
HashMap<String, String> hm = list.get(position);
String date=hm.get("date");
long l = Long.parseLong(date);
long unixTime = System.currentTimeMillis();
CharSequence datedate=DateUtils.getRelativeTimeSpanString(l, unixTime, 1);
String status = hm.get("status");
String who = hm.get("who");
if(hm.get("message").contains("[[pic_message]]"))
{
String picName=hm.get("message").replace("[[pic_message]]", "");
final String picPath1=Environment.getExternalStorageDirectory()+"/App/sent_pics/"+picName+".jpg";
File file = new File(picPath);
if(file.exists())
{
new AsyncTask<ViewHolder, Void, Bitmap>() {
private ViewHolder v;
Bitmap bm;
@Override
protected Bitmap doInBackground(ViewHolder... params) {
v = params[0];
bm = decodeSampledBitmapFromResource(picPath1,100,100);
return bm;
}
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
if (v.img.getTag().equals(position+"img")) {
v.img.setImageBitmap(result);
}
}
}.execute(holder);
}else{
holder.img.setImageBitmap(null);
}
}else{
holder.img.setImageBitmap(null);
Spannable msg =getSmiledText(getApplicationContext(),hm.get("message"));
holder.mMsg.setText(msg);
}
holder.mDate.setText(datedate);
return convertView;
问题是什么 -
列表视图显示,但图像显示在随机列表视图项。我经常搜索这类问题,尝试过但却没有运气。 asyntask代码来自 Google- Use A Background Thread. 。从上面看,我没有设置任何holder.mMsg.setText(msg);
,但是无论何时显示图像,它们都伴随着一个msg,这是不可取的。当显示图像时,滚动也是类似的延迟。我见过许多消息传递应用程序,它们运行得非常顺利,而且这些项目永远不会混淆。那么他们使用了什么。另外,在谷歌搜索这个问题时,一个答案建议我们应该删除converView if else
,然后一切都会好的。但那会产生我不想要的性能问题。
修改
图片显示没有问题,但主要问题是它们以随机顺序显示。
像这样 - 我滚动到图像信息,它们会显示出来。然后我再次滚动,现在图像显示在其他列表视图项目中。我的猜测是,相同的视图(原来一直保持图像)现在被其他人使用,但图像保留在那里。我该如何解决这个问题?并使列表视图像IM应用程序一样流畅(即使是图像)?
答案 0 :(得分:3)
这是因为Android ListView重用了Views,所以当你的Asynctask
执行donInBackground时,用户已经在做其他事情了,而你的代码对此一无所知。 (所以它会把图像放在一起)
我会使用Picasso
来避免这个问题,让其他人来处理您的问题。
我使用以下方法在我的应用程序(联系电话)中处理了这个问题:
WeakReference<>
,以便在完成后检查ImageView是否仍然有效并将位图放入其中。更新缓存。每当调用.getview时,检查图像是否在缓存中,如果它在缓存中直接放入,或者启动asynctask。
Bitmap bitmap = cache.get(number);
if (bitmap == null) {
Log.d(TAG, "I will download image for " + name + ".");
// i set a dummy image to avoid to show the wrong picture
holder.contactPhoto.setImageResource(R.drawable.ic_action_person);
loadUserProfilePhoto(number, holder.contactPhoto);
}
else {
// show it directly
Log.d(TAG, "I already have " + name + " in cache.");
holder.contactPhoto.setImageBitmap(bitmap);
}
如果你看到,它可能会显示另一张图片而不是用户照片,而它仍在加载它,所以我设置了一张虚拟照片而不是旧照片。
这不是最好的实施方式,但它告诉您,自己实施并正确执行它可能非常困难。
阅读Picasso文档并了解它如何在您的代码中实现它(它很简单,它只是一行。)
答案 1 :(得分:1)
问题在于listview不断刷新它。
所以你的所有代码都很好,但只需在holder.img中设置默认图像,而不是将其设为null holder.img.setImageBitmap(null);
也可能处于异步状态,您需要在加载图像时设置default_image。
答案 2 :(得分:0)
如果您想要动态显示图像,我认为您应该使用SurfaceView。它速度更快,刷新率更高。我制作了一个视频流应用程序,我尝试在ImageView上显示每个视频帧,但失败了。但是当我尝试使用SurfaceVIew时,效果很好。