Android开发之listview优化+图片异步加载+避免图片显示闪烁(修改版)

来源:互联网 发布:ssm项目管理系统源码 编辑:程序博客网 时间:2024/05/18 03:03

小鹿路过此地。。心热之下写写Android开发中的listview运用(闲的没事干,改动了一点代码,但实现功能不变)

小鹿学Android开发已有两年多了,总算有一点点小收获,虽算不上大牛大神级人物,但有些东西可以和一家一起分享一起交流一起学习一起进步...。还有,望查看此文章的废话不多说,直接主题

(注:此内容适合有点Android开发基础的)

学习过Android开发的人都知道listview这个控件了吧,意思就是说listview对我们这些Android开发人员来说并不陌生了。Android开发中使用listview说简单并不简单,说难也不是难,总之...看你怎么开发和使用它了

此内容讲解listview的优化+图片异步加载+避免图片显示闪烁等问题,由于小鹿第一次写这个博客,文章格式不懂怎么排布,乱点请不要喷,仅供大家一起交流学习。

说明实现原理:

大家学过listview图片异步加载等知识都知道,网上有很多很好的博客文章,实现原理大家也知道得差不多了

小鹿的这篇博客文章的listview也跟网上那些大同小异。知识上的一些细节有稍微的改动。

1、getview中的view重用,用使用viewholder。

2、listview中图片显示为当前界面图片显示。

3、滑动时停止加载,停止滑动时加载图片显示与listview界面。

4、给图片设置标签,判断并实现避免闪烁功能

5、异步加载过程就不用多说了....

看代码:(建议大家拷贝到项目中,这样会好看得多····)

显示信息源码:FerrariMessage.java

public class FerrariMessage {public static String[] Names = { "法拉利1", "法拉利2", "法拉利3", "法拉利4", "法拉利5","法拉利6", "法拉利7", "法拉利8", "法拉利9", "法拉利10", "法拉利11", "法拉利12", "法拉利13","法拉利14", "法拉利15", "法拉利16", "法拉利17", "法拉利18", "法拉利19", "法拉利20"};public static String[] Pics = { "901万", "902万", "903万", "904万", "905万","906万", "907万", "908万", "909万", "910万", "911万", "912万", "913万","914万", "915万", "916万", "917万", "918万", "919万", "920万" };public static String[] Urls = {"http://pic7.nipic.com/20100518/3409334_031036043513_2.jpg","http://pic7.nipic.com/20100521/1383578_011117510279_2.jpg","http://pic7.nipic.com/20100515/1383578_012657947151_2.jpg","http://xm.05927.com/UploadFiles/pic_2008121110263688.jpg","http://pic5.nipic.com/20100129/1295091_171443267500_2.jpg","http://pic4.nipic.com/20090925/3054494_105159945284_2.jpg","http://s9.knowsky.com/bizhi/l/35001-45000/200952904410415637552.jpg","http://picm.bbzhi.com/qichebizhi/gaoqingqichebizhixinshang/gaoqingqichebizhixinshang_423950_m.jpg","http://pic7.nipic.com/20100524/1383578_033343366370_2.jpg","http://www.lyt.com.cn/lytongger/uploads/201104/1302940767MbGrMW2F.jpg","http://img1.100ye.com/img1/4/996/468/10494468/msgpic/51043248.jpg","http://pic3.nipic.com/20090709/2082016_175148046_2.jpg","http://file-ps.sioe.cn/201006/5/B6132219150.jpg","http://home.tongyi.com/attachment/201001/23/332350_1264213529hJj2.jpg","http://f.hiphotos.bdimg.com/album/w%3D2048/sign=4e37a00c14ce36d3a20484300ecb3887/3801213fb80e7bec41655f372e2eb9389a506bac.jpg","http://gi1.md.alicdn.com/bao/uploaded/i1/TB1jFUUFVXXXXaRXXXXXXXXXXXX_!!0-item_pic.jpg_430x430q90.jpg","http://gd4.alicdn.com/bao/uploaded/i4/TB13YjTFVXXXXXVaXXXXXXXXXXX_!!0-item_pic.jpg_400x400.jpg","http://gd3.alicdn.com/bao/uploaded/i3/TB1iI9pGpXXXXXwXXXXXXXXXXXX_!!0-item_pic.jpg_400x400.jpg","http://gd3.alicdn.com/bao/uploaded/i3/TB1UqnNGXXXXXaFXFXXXXXXXXXX_!!0-item_pic.jpg_400x400.jpg","http://gd3.alicdn.com/bao/uploaded/i3/TB1lNP7FVXXXXXnXXXXXXXXXXXX_!!0-item_pic.jpg_400x400.jpg" };}

主界面源代码:MainActivity.java

public class MainActivity extends Activity {private ListView mListView = null;private List<HashMap<String, Object>> mList = new ArrayList<HashMap<String, Object>>();private ViewHolder_ListViewAdapter adapter = null;private HashMap<String, Object> hashMap=null;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);initFile();setContentView(R.layout.activity_main);mListView = (ListView) findViewById(R.id.mListView);adapter = new ViewHolder_ListViewAdapter(mList, mListView,getApplicationContext());mListView.setAdapter(adapter); mList.clear();for (int i = 0; i < FerrariMessage.Urls.length; i++) {hashMap = new HashMap<String, Object>();hashMap.put("name", FerrariMessage.Names[i]);hashMap.put("pic",FerrariMessage.Pics[i]);hashMap.put("url", FerrariMessage.Urls[i]);mList.add(hashMap);}adapter.notifyDataSetChanged();}private void initFile() {File file2 = new File(Environment.getExternalStorageDirectory()+ "/test/");if (!file2.exists()) {file2.mkdirs();}}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();File file = new File(Environment.getExternalStorageDirectory()+ "/test");deleteFile(file);}// 将SD卡文件删除private void deleteFile(File file) {if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {if (file.exists()) {if (file.isFile()) {file.delete();}// 如果它是一个目录else if (file.isDirectory()) {// 声明目录下所有的文件 files[];File files[] = file.listFiles();for (int i = 0; i < files.length; i++) { // 遍历目录下所有的文件deleteFile(files[i]); // 把每个文件 用这个方法进行迭代}}file.delete();}}}}

适配器:ViewHolder_ListViewAdapter.java

public class ViewHolder_ListViewAdapter extends BaseAdapter {private List<HashMap<String, Object>> mList;private LayoutInflater inflater = null;private ImageRegister imageRegister=null;private ListView mListView=null;public ViewHolder_ListViewAdapter(List<HashMap<String, Object>> list,ListView listView, Context context) {this.mList = list;this.imageRegister = new ImageRegister();this.mListView = listView;this.mListView.setOnScrollListener(onScrollListener);inflater = LayoutInflater.from(context);}@Overridepublic int getCount() {return mList.size();}@Overridepublic Object getItem(int position) {return mList.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(final int position, View v, ViewGroup parent) {ViewHolder vh = null;if (v == null) {vh = new ViewHolder();v = inflater.inflate(R.layout.item_listview, null);vh.title1 = (TextView) v.findViewById(R.id.title1);vh.title2 = (TextView) v.findViewById(R.id.title2);vh.imageView = (ImageView) v.findViewById(R.id.imageView);v.setTag(vh);} else {vh = (ViewHolder) v.getTag();}mListView.setTag(mList.get(position).get("url"));vh.title1.setText(mList.get(position).get("name").toString());vh.title2.setText(mList.get(position).get("pic").toString());vh.imageView.setBackgroundResource(R.drawable.ic_launcher);vh.imageView.setTag(mList.get(position).get("url").toString());imageRegister.loadImage(position, vh.imageView, mList.get(position).get("url").toString(), "test");return v;}private class ViewHolder {TextView title1;TextView title2;ImageView imageView;}AbsListView.OnScrollListener onScrollListener = new OnScrollListener() {@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {// TODO Auto-generated method stubswitch (scrollState) {case AbsListView.OnScrollListener.SCROLL_STATE_FLING:imageRegister.Lock();break;case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:loadImage();break;case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:imageRegister.Lock();break;}}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {}};protected void loadImage() {// TODO Auto-generated method stubint start = mListView.getFirstVisiblePosition();int end = mListView.getLastVisiblePosition();if (end >= getCount()) {end = getCount() - 1;}imageRegister.setLoadLimit(start, end);imageRegister.unLock();}}

异步加载类:ImageRegister.java

public class ImageRegister {private Object lock = new Object();private boolean mAllowLoad = true;private boolean firstLoad = true;private int mStartLoadLimit = 0;private int mStopLoadLimit = 0;final Handler handler = new Handler();private HashMap<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();public void setLoadLimit(int startLoadLimit, int stopLoadLimit) {if (startLoadLimit > stopLoadLimit) {return;}mStartLoadLimit = startLoadLimit;mStopLoadLimit = stopLoadLimit;}public void restore() {mAllowLoad = true;firstLoad = true;}public void Lock() {mAllowLoad = false;firstLoad = false;}public void unLock() {mAllowLoad = true;synchronized (lock) {lock.notifyAll();}}public void loadImage(final Integer position, final ImageView imageView,final String imageUrl, final String fileName) {new Thread(new Runnable() {@Overridepublic void run() {if (!mAllowLoad) {synchronized (lock) {try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}}if (mAllowLoad && firstLoad) {loadImage2(position,imageUrl, imageView, fileName);}if (mAllowLoad && position<= mStopLoadLimit && position >= mStartLoadLimit) {loadImage2(position,imageUrl, imageView, fileName);}}}).start();}private void loadImage2(final Integer position,final String mImageUrl, final ImageView imageView,final String fileName) {if (imageCache.containsKey(mImageUrl)) {SoftReference<Drawable> softReference = imageCache.get(mImageUrl);final Drawable d = softReference.get();if (d != null) {handler.post(new Runnable() {@SuppressLint("NewApi") @Overridepublic void run() {if (mAllowLoad) {if (imageView.getTag().equals(mImageUrl)) {imageView.setBackground(d);}}}});return;}}try {final Drawable d = loadImageFromUrl(position,imageView,mImageUrl, fileName);if (d != null) {imageCache.put(mImageUrl, new SoftReference<Drawable>(d));handler.post(new Runnable() {@SuppressLint("NewApi") @Overridepublic void run() {if (mAllowLoad) {if (imageView.getTag().equals(mImageUrl)) {imageView.setBackground(d);}}}});}} catch (IOException e) {handler.post(new Runnable() {@Overridepublic void run() {imageView.setBackgroundResource(R.drawable.ic_launcher);}});e.printStackTrace();}}@SuppressLint("NewApi") public Drawable loadImageFromUrl(Integer position,ImageView imageView,String url, String fileName)throws IOException {if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {String imageName = url.substring(url.lastIndexOf("/"));String pathName = (Environment.getExternalStorageDirectory() + "/"+ fileName + imageName);File f = new File(pathName);if (f.exists()) {Bitmap bitmap = compressImageFromFile(pathName);@SuppressWarnings("deprecation")BitmapDrawable d = new BitmapDrawable(bitmap);System.out.println("加载了第:"+position);return d;}else{System.out.println("下载了第:"+position);URL m = new URL(url);InputStream inputStream = (InputStream) m.getContent();DataInputStream in = new DataInputStream(inputStream);FileOutputStream out = new FileOutputStream(f);byte[] buffer = new byte[1024];int byteRead = 0;while ((byteRead = in.read(buffer)) != -1) {out.write(buffer, 0, byteRead);}in.close();out.close();return loadImageFromUrl(position,imageView,url, fileName);}} else {URL m = new URL(url);InputStream inputStream = (InputStream) m.getContent();Drawable drawable = Drawable.createFromStream(inputStream, null);inputStream.close();return drawable;}    }private Bitmap compressImageFromFile(String srcPath) {BitmapFactory.Options newOpts = new BitmapFactory.Options();newOpts.inJustDecodeBounds = true;Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);newOpts.inJustDecodeBounds = false;int w = newOpts.outWidth;int h = newOpts.outHeight;float hh = 100f;float ww = 120f;int be = 1;if (w > h && w > ww) {be = (int) (newOpts.outWidth / ww);} else if (w < h && h > hh) {be = (int) (newOpts.outHeight / hh);}if (be <= 0)be = 1;newOpts.inSampleSize = be;newOpts.inPreferredConfig = Config.ARGB_8888;newOpts.inPurgeable = true;newOpts.inInputShareable = true;bitmap = BitmapFactory.decodeFile(srcPath, newOpts);return bitmap;}}

mainactivity界面的布局文件activity_main.xml

<LinearLayout 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"    android:orientation="vertical" >     <ListView        android:id="@+id/mListView"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:cacheColorHint="#00000000"        android:dividerHeight="1.0dip"        android:listSelector="#00000000" /></LinearLayout>

listview条目的布局文件item_listview.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="80dp"    android:orientation="horizontal" >         <ImageView         android:id="@+id/imageView"        android:layout_width="0dp"        android:layout_height="80dp"        android:layout_weight="1.0"        />        <TextView        android:id="@+id/title1"        android:layout_width="0dp"        android:layout_height="fill_parent"        android:layout_weight="1.0"        android:gravity="center"        android:text="" />    <TextView        android:id="@+id/title2"        android:layout_width="0dp"        android:layout_height="fill_parent"        android:layout_weight="1.0"        android:gravity="center"        android:text="" />    <TextView        android:id="@+id/title3"        android:layout_width="0dp"        android:layout_height="fill_parent"        android:layout_weight="1.0"        android:gravity="center"        android:text="" />    <TextView        android:id="@+id/title4"        android:layout_width="0dp"        android:layout_height="fill_parent"        android:layout_weight="1.0"        android:gravity="center"        android:text="" /></LinearLayout>

最后,在androidmanifest.xml中添加权限

  

    <uses-permission android:name="android.permission.INTERNET" />    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />    <uses-permission android:name="android.permission.RESTART_PACKAGES" />

点评:此项目又优点也有缺点,我直接说缺点好了:①当网速不好的时候,下载图片速度慢,显示在listview界面有时图片不全(暂时没有解决方案,希望大家一起交流)。②界面太简单(这靠大家设计UI了,小鹿能力有限)。

代码已奉上完了,小鹿第一次用博客写文章,本来想给大家发上demo,可小鹿不懂怎么发,时间也不多了,希望大家查看此文章后能一起交流技术,此文章有不足之处请大家点评。。。。小鹿要睡觉了。。。希望能和大家一起交流。。。午安



0 0