解决图片加载时闪烁和图片错位的问题--面试常被问到

最近在为面试做准备,真的好累的说啊。。比每天上课还累。从9点20睡到10点又起来了。。觉着还是写一篇博客吧。
我要坚持写博客。。坚持写博客。。
1,首先说一下图片闪烁和错位的原理:
因为在使用ListView时,为了ListView提高view的复用性,所以需要使用到convertView。
当convertView不为null,如图所示:

分析:
     当网络不好时,手指向上滑动,将position=1滑出了屏幕,紧接着position=6的Item出现在下方,
     因为convertView此时!=null, 所以position=6的Item复用的是position=1的Item,假设网络很慢,
     刚才Item1滑出屏幕时数据还没有加载进来,但是当item6出现时, 正好数据加载成功, 这样就将之前
     应该加载到item1的数据加载到了item6上,所以就出现了图片错位的现象。
     然而因为item6有自己的 图片所属,所以当网络此时恰好又变好时,正好将Item6该有的图片加载进来,
    所以此时Item6上之前 加载的Item1图片又会替换成Item6真正的图片。。所以此时就又会出现图片闪烁的问题。

2,遇到这种问题的解决办法如下:
     给每一个ImageView控件都设置一个Tag。通过调用setTag,来给相应的ImageView设置其对应的标志。
     举个很俗的例子就是:正如猪肉出场时往身上盖的一个戳一样。标志每一头猪都有一个唯一的标识。
     然后在获取图片时,通过getTag来与加载进来的图片进行比较,如果二者相同,说明是同一ImageView的。
     否则就不是。
    还可以给每一个ImageView控件设置一个默认显示的背影图片。。这样当网络不好时就显示默认的背景即可。
 
 不多说了。。直接上代码!!!
前期准备工作:
Tomcat打开,并且在Tomcat的\webapps\ROOT目录下放置几张图片。
代码中的图片路径名为: http://192.168.12.93:8080/1.png,将 http://192.168.12.93换成你自己的。
将加载图片的方法单独放在了一个类中: NetImageLoader.java
MainActivity.java中的代码:

       
       
package com.example.imagelistview;
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.app.Activity;
import android.graphics.Bitmap;
public class MainActivity extends Activity {
private ListView listView;
private List<String> urlList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取ListView控件
listView = (ListView) findViewById(R.id.lv);
urlList = new ArrayList<String>();
//添加图片到list集合中去。
urlList.add("http://192.168.12.93:8080/1.png");
urlList.add("http://192.168.12.93:8080/2.png");
urlList.add("http://192.168.12.93:8080/3.png");
urlList.add("http://192.168.12.93:8080/4.png");
urlList.add("http://192.168.12.93:8080/5.png");
urlList.add("http://192.168.12.93:8080/6.png");
urlList.add("http://192.168.12.93:8080/7.png");
urlList.add("http://192.168.12.93:8080/8.png");
urlList.add("http://192.168.12.93:8080/9.png");
urlList.add("http://192.168.12.93:8080/10.png");
urlList.add("http://192.168.12.93:8080/11.png");
urlList.add("http://192.168.12.93:8080/12.png");
urlList.add("http://192.168.12.93:8080/13.png");
urlList.add("http://192.168.12.93:8080/14.png");
//给ListView设置适配器
listView.setAdapter(new MyAdapter());
}
//继承自BaseAdapter的适配器
class MyAdapter extends BaseAdapter{
@Override
public int getCount() {
//返回list的数目
return urlList.size();
}
@Override
public Object getItem(int position) {
return urlList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
//为了优化ListView,所以定义一个类用来存放ListView中要用到的所有控件,这样就不用
//每次用到的时候去一次次查找。
ViewHolder viewHolder = null;
if(convertView == null){
viewHolder = new ViewHolder();
//将字条目的布局填充到ListView中去
convertView = View.inflate(getApplicationContext(), R.layout.item, null);
viewHolder.iv = (ImageView) convertView.findViewById(R.id.iv);
//这一步必不可少
convertView.setTag(viewHolder);
}else{
//这一步必不可少
viewHolder = (ViewHolder) convertView.getTag();
}
//解决图片错位和图片闪烁的方法:为每一ImageView设置标志
viewHolder.iv.setTag(urlList.get(position));
//为每一个ImageView设置默认的背景。
viewHolder.iv.setImageResource(R.drawable.ic_launcher);
new NetImageLoader() {
@Override
public void loadImage(ImageView imageView, Bitmap bitmap) {
//图片错误,闪烁
if(imageView.getTag().equals(urlList.get(position))){
imageView.setImageBitmap(bitmap);
}
}
}.downLoadImage(urlList.get(position), viewHolder.iv);
//开启一个线程去下载相应图片
return convertView;
}
}
class ViewHolder{
ImageView iv;
}
}
         
         

NetImageLoader.java中的代码:
         
         
package com.example.imagelistview;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;
public abstract class NetImageLoader {
private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
Bitmap bitmap = (Bitmap) msg.obj;
//回调
loadImage(imageView, bitmap);
};
};
public abstract void loadImage(ImageView imageView,Bitmap bitmap);
private ImageView imageView;
public void downLoadImage(final String imgUrl,ImageView imageView){
this.imageView = imageView;
new Thread(){
public void run() {
try {
URL url = new URL(imgUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
InputStream is = connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(is);
sleep(3000);
Message message = new Message();
message.obj = bitmap;
handler.sendMessage(message);
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
}
}

activity_main.xml中的布局;
       
       
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<ListView
android:id="@+id/lv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
item.xml:
       
       
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<ImageView
android:id="@+id/iv"
android:layout_width="60dp"
android:layout_height="60dp"/>
</RelativeLayout>

OK~






    
    
package com.example.imagelistview;
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.app.Activity;
import android.graphics.Bitmap;
public class MainActivity extends Activity {
private ListView listView;
private List<String> urlList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取ListView控件
listView = (ListView) findViewById(R.id.lv);
urlList = new ArrayList<String>();
//添加图片到list集合中去。
urlList.add("http://192.168.12.93:8080/1.png");
urlList.add("http://192.168.12.93:8080/2.png");
urlList.add("http://192.168.12.93:8080/3.png");
urlList.add("http://192.168.12.93:8080/4.png");
urlList.add("http://192.168.12.93:8080/5.png");
urlList.add("http://192.168.12.93:8080/6.png");
urlList.add("http://192.168.12.93:8080/7.png");
urlList.add("http://192.168.12.93:8080/8.png");
urlList.add("http://192.168.12.93:8080/9.png");
urlList.add("http://192.168.12.93:8080/10.png");
urlList.add("http://192.168.12.93:8080/11.png");
urlList.add("http://192.168.12.93:8080/12.png");
urlList.add("http://192.168.12.93:8080/13.png");
urlList.add("http://192.168.12.93:8080/14.png");
//给ListView设置适配器
listView.setAdapter(new MyAdapter());
}
//继承自BaseAdapter的适配器
class MyAdapter extends BaseAdapter{
@Override
public int getCount() {
//返回list的数目
return urlList.size();
}
@Override
public Object getItem(int position) {
return urlList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
//为了优化ListView,所以定义一个类用来存放ListView中要用到的所有控件,这样就不用
//每次用到的时候去一次次查找。
ViewHolder viewHolder = null;
if(convertView == null){
viewHolder = new ViewHolder();
//将字条目的布局填充到ListView中去
convertView = View.inflate(getApplicationContext(), R.layout.item, null);
viewHolder.iv = (ImageView) convertView.findViewById(R.id.iv);
//这一步必不可少
convertView.setTag(viewHolder);
}else{
//这一步必不可少
viewHolder = (ViewHolder) convertView.getTag();
}
//解决图片错位和图片闪烁的方法:为每一ImageView设置标志
viewHolder.iv.setTag(urlList.get(position));
//为每一个ImageView设置默认的背景。
viewHolder.iv.setImageResource(R.drawable.ic_launcher);
new NetImageLoader() {
@Override
public void loadImage(ImageView imageView, Bitmap bitmap) {
//图片错误,闪烁
if(imageView.getTag().equals(urlList.get(position))){
imageView.setImageBitmap(bitmap);
}
}
}.downLoadImage(urlList.get(position), viewHolder.iv);
//开启一个线程去下载相应图片
return convertView;
}
}
class ViewHolder{
ImageView iv;
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值