网上摘的一个ListView异步更新图片的例子

本文深入探讨了Android应用开发过程中的关键技术和性能优化策略,包括使用最新开发工具、优化代码结构、提升用户体验等方面,旨在帮助开发者提高应用的运行效率和稳定性。

 

先把xml上上... main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />
    <ListView 
    	 android:layout_width="fill_parent" 
   		 android:layout_height="wrap_content" 
   		 android:id="@+id/lv_list"
    ></ListView>
</LinearLayout>
item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:orientation="horizontal"
              android:layout_height="wrap_content">

        <ImageView android:id="@+id/image"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                  android:layout_gravity="left"  
                  android:layout_weight="7"
               	   android:paddingLeft="10px"
                   />

        <TextView android:id="@+id/text"
                  android:layout_width="wrap_content"
               		 android:textSize="16sp"  
					android:textStyle="bold|italic"  
					android:gravity="right"
					android:layout_weight="3"
                  android:layout_height="wrap_content"/>
</LinearLayout>


2个类,1个是用来保存布局孵化的控件类,一个是定义显示内容的类
package com.wangs.demo;

/** 获取的对象 **/
public class ImageAndText {
    private String imageUrl;
    private String text;
 
    public ImageAndText(String imageUrl, String text) {
        this.imageUrl = imageUrl;
        this.text = text;
    }
    public String getImageUrl() {
        return imageUrl;
    }
    public String getText() {
        return text;
    }
}

package com.wangs.demo;

import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

 /**
  * 
  *UI布局要用到的view
  */
public class ViewCache {
 
    private View baseView;   //需要孵化的listview
    private TextView textView;
    private ImageView imageView;
 
    public ViewCache(View baseView) {
        this.baseView = baseView;
    }
 
    public TextView getTextView() {
        if (textView == null) {
            textView = (TextView) baseView.findViewById(R.id.text);
        }
        return textView;
    }
 
    public ImageView getImageView() {
        if (imageView == null) {
            imageView = (ImageView) baseView.findViewById(R.id.image);
        }
        return imageView;
    }
}


异步加载图片,保存到map

package com.wangs.demo;

import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.URL;
import java.text.Collator;
import java.util.HashMap;

import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;

/**
 * 异步加载图片
 *
 */
public class AsyncImageLoader {

	private HashMap<String, SoftReference<Drawable>> imageCache;

	public AsyncImageLoader() {
		imageCache = new HashMap<String, SoftReference<Drawable>>();
	}

	public Drawable loadDrawable(final String imageUrl,
			final ImageCallback imageCallback) {
		if (imageCache.containsKey(imageUrl)) {
			SoftReference<Drawable> softReference = imageCache.get(imageUrl);  //软引用释放内存
			Drawable drawable = softReference.get();  //软引用取出图片
			if (drawable != null) {
				return drawable;  //返回
			}
		}
		/**
		 * 后2步是开启新线程异步用handler发送drawable对象 (用来保存到hashmap)
		 */
		final Handler handler = new Handler() {
			@Override
			public void handleMessage(Message message) {
				imageCallback.imageLoaded((Drawable) message.obj, imageUrl);
			}
		};
		new Thread() {
			@Override
			public void run() {
				Drawable drawable = loadImageFromUrl(imageUrl);  //加载图片
				imageCache.put(imageUrl, new SoftReference<Drawable>(drawable)); //把图片的弱引用路径放入hashmap
				Message message = handler.obtainMessage(0, drawable);
				handler.sendMessage(message);
			}
		}.start();
		return null;
	}

	public static Drawable loadImageFromUrl(String url) {
		InputStream inputStream;
		try {
			inputStream = new URL(url).openStream();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		return Drawable.createFromStream(inputStream, "src");
	}

	public interface ImageCallback {
		public void imageLoaded(Drawable imageDrawable, String imageUrl);
	}
}

listview适配器

package com.wangs.demo;

import java.util.List;

import com.wangs.demo.AsyncImageLoader.ImageCallback;

import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

/* 适配器,接收3个参数*/
public class ImageAndTextListAdapter extends ArrayAdapter<ImageAndText> {
 
	private ListView listView;
    private AsyncImageLoader asyncImageLoader;
 
    public ImageAndTextListAdapter(Activity activity, List<ImageAndText> imageAndTexts, ListView listView) {
        super(activity, 0, imageAndTexts);
        this.listView = listView;
        asyncImageLoader = new AsyncImageLoader();
    }
 
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Activity activity = (Activity) getContext();
 
        // Inflate the views from XML
        View rowView = convertView;
        ViewCache viewCache;
        if (rowView == null) {
            LayoutInflater inflater = activity.getLayoutInflater();
            rowView = inflater.inflate(R.layout.image_and_text_row, null);
            viewCache = new ViewCache(rowView);     //孵化出布局内容
            rowView.setTag(viewCache);       //设置布局缓存对象标记 ,,这个方法很重要
            System.out.println("new rowview");
        } else {
            viewCache = (ViewCache) rowView.getTag();  //布局有了就直接获取
            System.out.println("no new rowview"); //第一次创建后,都是从这边取的
        }
        ImageAndText imageAndText = getItem(position);       //每一个item就是一个imageandtext对象
 
        // Load the image and set it on the ImageView 加载图片和设置
        String imageUrl = imageAndText.getImageUrl();
        ImageView imageView = viewCache.getImageView();
        imageView.setTag(imageUrl);
        Drawable cachedImage = asyncImageLoader.loadDrawable(imageUrl, new ImageCallback() { 
            public void imageLoaded(Drawable imageDrawable, String imageUrl) {      //实现自定义的回调函数
                ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);
                if (imageViewByTag != null) {
                    imageViewByTag.setImageDrawable(imageDrawable);
                }
            }
        });
        imageView.setImageDrawable(cachedImage);//设置异步加载的image
 
        // Set the text on the TextView //通过布局UI得到信息并设置到内容上
        TextView textView = viewCache.getTextView();      
        textView.setText(imageAndText.getText());
 
        return rowView;
    }
}

activity启动:

package com.wangs.demo;

import java.util.ArrayList;
import java.util.List;

import com.wangs.demo.AsyncImageLoader.ImageCallback;

import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class ImageListURLActivity extends Activity {

	/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        ListView listview = (ListView) this.findViewById(R.id.lv_list);
        List<ImageAndText> imageAndTexts = new ArrayList<ImageAndText>();
        ImageAndText it = new ImageAndText("http://www.169pp.com/files/images/20773.jpg", "漫画妹妹");
        ImageAndText it2 = new ImageAndText("http://www.169pp.com/files/images/26580.jpg", "大波妹妹");
        ImageAndText it3 = new ImageAndText("http://www.169pp.com/files/images/28048.jpg", "大波妹妹");
        imageAndTexts.add(it);
        imageAndTexts.add(it2);
        imageAndTexts.add(it3);
        for(int i=0;i<100;i++){  //测试正常,但如果url图片太大了会造成内存溢出
        	ImageAndText it4= new ImageAndText("http://www.169pp.com/files/images/28048.jpg", "大波妹妹");
        	imageAndTexts.add(it4);
        }
        ImageAndTextListAdapter adapter = new ImageAndTextListAdapter(this, imageAndTexts, listview);
        listview.setAdapter(adapter);
        adapter.notifyDataSetChanged();
    }
    
}

修改: loadimage方法,2.2提供的微缩图的类的静态方法
	public static Bitmap loadImageFromUrl(String url) {
		InputStream inputStream;
		try {
			inputStream = new URL(url).openStream();
			Bitmap b = BitmapFactory.decodeStream(inputStream);
			return ThumbnailUtils.extractThumbnail(b, 40, 40);
		} catch (IOException e) {
			
			throw new RuntimeException(e);
		}
		//return Drawable.createFromStream(inputStream, "src");
	}

 
 
-------------------------------------------------------------------------------scroll---------------
public class MainActivity extends Activity {
    ListView listView;
    private ArrayAdapter<String> adapter;
    List<String> data = new ArrayList<String>();
    View loadingView;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       // data = PersonService.getNames(0, 20);
        
        loadingView = getLayoutInflater().inflate(R.layout.loading, null);
        
        adapter = new ArrayAdapter<String>(this, R.layout.list_item,
        		R.id.name, data);
        
        listView = (ListView) this.findViewById(R.id.listView);
       listView.setOnScrollListener(new ScrollListener());
      //  listView.addFooterView(loadingView);
        listView.setAdapter(adapter);
    }
    
    int nextpage = 1;
    int currentpage = 0;
    private final class ScrollListener implements OnScrollListener{
    	private int number = 20;
		@Override
		public void onScrollStateChanged(AbsListView view, int scrollState) {
			Log.i("Test", "onScrollStateChanged(scrollState="+ scrollState + ")");
		}
		
		@Override
		public void onScroll(AbsListView view, int firstVisibleItem,
				int visibleItemCount, int totalItemCount) {
			Log.i("Test", "onScroll(firstVisibleItem="+ firstVisibleItem+
					"visibleItemCount="+visibleItemCount+ "totalItemCount="+totalItemCount + ")");
			//listView.getLastVisiblePosition()
			if(firstVisibleItem + visibleItemCount == totalItemCount){//下一页
				if(totalItemCount>0) nextpage = totalItemCount / number + 1;
				
				if(currentpage!=nextpage){
					listView.addFooterView(loadingView);//显示数据正在加载
					//开线程{得到数据,然后发送消息}
					handler.sendMessageDelayed(handler.obtainMessage(1, totalItemCount), 3000);
					currentpage = nextpage;
				}
			}
		}
    }
    
    Handler handler = new Handler(){
		public void handleMessage(Message msg) {
			data.addAll(PersonService.getNames((Integer)msg.obj, 20));
			adapter.notifyDataSetChanged();
			listView.removeFooterView(loadingView);//当数据加载完后,删除提示
		}
    };

--------------------------------------------------------------------------------------另外一个异步加载的--------------------------
public class ImageAdapter extends BaseAdapter {
	private List<String> data;//存放图片路径
	private int sourceid;
	private LayoutInflater layoutInflater;
	File saveDir;
	public ImageAdapter(List<String> data, Context context, int sourceid) {
		this.data = data;
		this.sourceid = sourceid;
		layoutInflater = LayoutInflater.from(context);
		saveDir = new File(Environment.getExternalStorageDirectory(),"cache");
		if(!saveDir.exists()) saveDir.mkdirs();
	}

	@Override
	public int getCount() {
		return data.size();
	}

	@Override
	public Object getItem(int position) {
		return data.get(position);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ImageView imageView;
		if(convertView == null){
			convertView = layoutInflater.inflate(sourceid, null);
			imageView = (ImageView) convertView.findViewById(R.id.imageView);
			convertView.setTag(imageView);
		}else{
			imageView = (ImageView) convertView.getTag();
		}
		showImage2(imageView, data.get(position));
		return convertView;
	}
	/*
	private void showImage(final ImageView imageView, final String imagepath) {
		final Handler handler = new Handler(){
			public void handleMessage(Message msg) {
				imageView.setImageURI((Uri) msg.obj);//显示照片
			}
		};
		
		Runnable loadImageTask = new Runnable() {
			public void run() {
				try {
					Uri uri = ImageService.getImage(imagepath, saveDir);
					handler.sendMessage(handler.obtainMessage(1, uri));
					
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		};
		
		new Thread(loadImageTask).start();
		
	}
	*/

	private void showImage2(ImageView imageView, String path) {
		LoadImageTask task = new LoadImageTask();
		task.execute(imageView, path);//参数传给了doInBackground()
	}
	
	private final class LoadImageTask extends AsyncTask<Object, Integer, Uri>{
		ImageView imageView;
		String imagepath;
		@Override
		protected Uri doInBackground(Object... params) {//耗时操作,运行在子线程
			imageView = (ImageView) params[0];
			imagepath = (String) params[1];
			try {
				return ImageService.getImage(imagepath, saveDir);
			} catch (Exception e) {
				e.printStackTrace();
			}
			return null;
		}
		@Override
		protected void onPostExecute(Uri result) {//doInBackground()的结果传入该方法,运行在UI线程
			imageView.setImageURI(result);//显示照片
		}
	}

public class ImageService {
	/**
	 * 获取图片,具有缓存功能
	 * @param path
	 * @param saveDir
	 * @return
	 * @throws Exception
	 */  
	public static Uri getImage(String path, File saveDir) throws Exception{
		String filename = MD5.getMD5(path) + path.substring(path.lastIndexOf("."));
		File imageFile = new File(saveDir, filename);
		if(imageFile.exists()){
			return Uri.fromFile(imageFile);
		}
		//否则从网络获取图片
		HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();
		conn.setConnectTimeout(5000);
		conn.setRequestMethod("GET");
		if(conn.getResponseCode() == 200){
			
			copyStream(conn.getInputStream(), new FileOutputStream(imageFile));
			return Uri.fromFile(imageFile);
		}
		return null;
	}

	private static void copyStream(InputStream inputStream, OutputStream outStream) throws Exception{
		byte[] buffer = new byte[1024];
		int len = 0;
		while((len = inputStream.read(buffer)) != -1){
			outStream.write(buffer, 0, len);
		}
		inputStream.close();
		outStream.close();
	}

	public static List<String> getImageInfos() throws Exception{
		String path = "http://192.168.1.101/web/list.xml";
		HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();
		conn.setConnectTimeout(5000);
		conn.setRequestMethod("GET");
		if(conn.getResponseCode() == 200){
			return parseXML(conn.getInputStream());
		}
		return null;
	}

	private static List<String> parseXML(InputStream xml) throws Exception{
		List<String> paths = new ArrayList<String>();
		XmlPullParser pullParser = Xml.newPullParser();
		pullParser.setInput(xml, "UTF-8");
		int event = pullParser.getEventType();
		while(event != XmlPullParser.END_DOCUMENT){
			if(event == XmlPullParser.START_TAG){
				if("image".equals(pullParser.getName())){
					paths.add(pullParser.getAttributeValue(0));
				}
			}
			event = pullParser.next();
		}
		return paths;
	}

public class MainActivity extends Activity {
    ListView listView;
    View loadingView;
    
    List<String> data = new ArrayList<String>();
    ImageAdapter adapter;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        loadingView = getLayoutInflater().inflate(R.layout.loading, null);
        listView = (ListView) this.findViewById(R.id.listView);
        try {
			//data = ImageService.getImageInfos();  //放在滚动的时候再加载
        	adapter =new ImageAdapter(data, this, R.layout.list_item);
        	listView.setOnScrollListener(new ScrollListener());
			listView.setAdapter(adapter);
		} catch (Exception e) {
			Toast.makeText(this, "获取图片失败", 1).show();
			e.printStackTrace();
		}
    }

	@Override
	protected void onDestroy() {   //销毁的时候把缓存清空了
		super.onDestroy();
		File saveDir = new File(Environment.getExternalStorageDirectory(),"cache");
		if(saveDir.exists()){
			for(File file : saveDir.listFiles()){
				file.delete();
			}
		}
	}
   //监听器
	
	 int nextpage = 1;
	    int currentpage = 0;
	    private final class ScrollListener implements OnScrollListener{
	    	private int number = 10;
			@Override
			public void onScrollStateChanged(AbsListView view, int scrollState) {
				Log.i("Test", "onScrollStateChanged(scrollState="+ scrollState + ")");
			}
			
			@Override
			public void onScroll(AbsListView view, int firstVisibleItem,
					int visibleItemCount, int totalItemCount) {
				Log.i("Test", "onScroll(firstVisibleItem="+ firstVisibleItem+
						"visibleItemCount="+visibleItemCount+ "totalItemCount="+totalItemCount + ")");
				//listView.getLastVisiblePosition()
				if(firstVisibleItem + visibleItemCount == totalItemCount){//下一页
					if(totalItemCount>0) nextpage = totalItemCount / number + 1;
					
					if(currentpage!=nextpage){
						listView.addFooterView(loadingView);//显示数据正在加载
						//开线程{得到数据,然后发送消息}
						try {
							//data = ImageService.getImageInfos();
						} catch (Exception e) {
							e.printStackTrace();
						} 
						handler.sendMessageDelayed(handler.obtainMessage(1, totalItemCount), 3000);
						currentpage = nextpage;
					}
				}
			}
	    }
	    Handler handler = new Handler(){
			public void handleMessage(Message msg) {
				try {
					data.addAll(ImageService.getImageInfos());   //每次往下拖后又重新获取数据。
					adapter.notifyDataSetChanged();
					listView.removeFooterView(loadingView);//当数据加载完后,删除提示
				} catch (Exception e) {
					Toast.makeText(MainActivity.this, "获取图片失败了..", 2).show();
					e.printStackTrace();
				}
			}
	    };
	

public class MD5 {

	public static String getMD5(String content) {
		try {
			MessageDigest digest = MessageDigest.getInstance("MD5");
			digest.update(content.getBytes());
			return getHashString(digest);
			
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return null;
	}
	
    private static String getHashString(MessageDigest digest) {
        StringBuilder builder = new StringBuilder();
        for (byte b : digest.digest()) {
            builder.append(Integer.toHexString((b >> 4) & 0xf));
            builder.append(Integer.toHexString(b & 0xf));
        }
        return builder.toString();
    }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值