小鹿路过此地。。心热之下写写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;
@Override
public 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();
}
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.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);
}
@Override
public int getCount() {
return mList.size();
}
@Override
public Object getItem(int position) {
return mList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public 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() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
switch (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;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
}
};
protected void loadImage() {
// TODO Auto-generated method stub
int 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() {
@Override
public 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") @Override
public 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") @Override
public void run() {
if (mAllowLoad) {
if (imageView.getTag().equals(mImageUrl)) {
imageView.setBackground(d);
}
}
}
});
}
} catch (IOException e) {
handler.post(new Runnable() {
@Override
public 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,可小鹿不懂怎么发,时间也不多了,希望大家查看此文章后能一起交流技术,此文章有不足之处请大家点评。。。。小鹿要睡觉了。。。希望能和大家一起交流。。。午安