android listview 懒加载,ListView结合软引用和懒加载

第一篇blog。。。希望能记住自己是怎么理解程序。。。

应该说这样的代码网上并不少,像我现在的代码其实也是跟着别人的代码写的。

文章写的是关于通过ListView显示异步加载的网上图片,并且实现缓存机制,图片在内存足够且已经存在缓存的情况下,直接从缓存把图片取出来,而不用多次从网上搜索图片。

文章涉及的知识点:

SoftReference(软引用):JDK设置的关于对象引用的一种级别。在软引用的情况下,只要内存足够,垃圾回收器就不会对它进行回收,内存不足时,才会对它回收。只要没有被回收,我们的程序就可以一直使用它。软引用主要用于高速缓存。

AsyncTask:为了访问UI线程的工具类,适用于简单的异步处理。使用时需要注意Task必须在UI线程中创建,execute方法必须在UI线程中调用,不要手动调用它的4个方法,task只能被执行一次。

4个方法(根据自己的需要选择1~4个方法的重写):onPreExecute();在实际后台操作前被UI线程调用,可以显示一个进度条

doInparams...);在上面操作后立即执行,主要负责耗时的后台计算< /span>

onProgressUpdate(values...);显示上面操作的进展情况,通常在进度条上显示进度

onPostExecute(result...);doInBackground执行后被UI线程调用,后台计算结果通过这一函数传给UI线程

需要加载的包:jericho-html-3.1 这个包应该是用来解析html语言用的

这个程序完成的功能:从豆瓣的新书主页把新书在listview上显示,不过程序代码要想同样获得不同网页的list进行显示,估计需要适当的修改,具体待会儿写一下,所以程序本身只是提供一个思路,如何解耦估计到时可以在这个程序基础上修改。。。因为跟着程序写得同时也在思考程序是怎么的流程,理解并记下来免得忘了。

程序:

查看网址的源代码,可以知道一本书的介绍的html标签如下设置:

根据标签我们可以设置Book.java

String name; String message ; String synopsis ;String path;

分别对应书的名字,基本信息,大纲,图片地址。

下面源程序引入的包名省略(可通过ctrl+shift+o导入):

public class BookDao {

public static List getAllBooks() throws Exception{

List list = new ArrayList();

URL url = new URL("http://book.douban.com/latest");

URLConnection conn = url.openConnection();

Source source = new Source(conn);

ListelList = source.getAllElements("li");

for(Element e:elList){

List childrenList = e.getChildElements();

if(childrenList.size()==2 && "div".equals(childrenList.get(0).getName())

&& "a".equals(childrenList.get(1).getName())){

Book book = new Book();

String name = childrenList.get(0).getAllElements().get(0).getTextExtractor().toString();

String message = childrenList.get(0).getAllElements().get(1).getTextExtractor().toString();

String synopsis = childrenList.get(0).getAllElements().get(2).getTextExtractor().toString();

String path = childrenList.get(1).getAllElements().get(1).getAttributeValue("src");

book.setBname(name);

book.setBmessage(message);

book.setBsynopsis(synopsis);

book.setBpathimg(path);

list.add(book);

}

}

return list;

}

}

****************

BookDao的方法getAllBooks()获得网址的所有图书:

通过Source获得链接的源,source.getAllElements("li")获得所有li标签包围的内容,getChildElements()获得其所有的子标签,找到子标签中如果是第一个子标签为div,第二个子标签为a的,获得div子标签下所有的子标签,并把其下子标签的内容取出来分别放入到book中,getAttributeValue("src")方法获得其图像的地址。最后将获得的图书加入到list中。因为不同网页对li标签下的设置不同,所以必须得根据需要打开的网页进行适当的设置。

***************

imgCache存放缓存的图片对象,loadImg(url)方法将传入的url解析成InputStream,通过Drawable.createFromStream(in ,null)方法将stream流转换成Drawable对象。

imgCache= new HashMap>();通过图像地址唯一标识图片作为Key,通过软引用图像。loadDraw(final String imgUrl,final ImgCallBack imgCallBack)判断是否存在缓存图片。如果没有缓冲,即开启线程去下载图片,同时将当前的图片放入到存放缓存图片的HashMap中。

public class MainActivity extends Activity {

private List list;

private ListView lv_book_list;

private LinearLayout loading;

private boolean isScroll = false;

private BookListAdapter adapter;

private boolean isloading = false;

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

lv_book_list = (ListView) this.findViewById(R.id.books_list);

loading = (LinearLayout) this.findViewById(R.id.progressll);

list = new ArrayList();

adapter = new BookListAdapter();

/**第一次加载*/

getData();

/**判断是否处于滚动状态或是否已经滚动到最底部*/

lv_book_list.setOnScrollListener(new OnScrollListener() {

@Override

public void onScroll(AbsListView view, int firstVisibleItem,

int visibleItemCount, int totalItemCount) {

// TODO Auto-generated method stub

if(totalItemCount <=0){

return ;

}

if(firstVisibleItem + visibleItemCount == totalItemCount){

if(isloading){

return ;

}

new AsyncTask>(){

@Override

protected List doInVoid... params) {

List listBooks = null;

try{

listBooks = BookDao.getAllBooks();

}catch(Exception e){

e.printStackTrace();

}

return listBooks;

}

protected void onPreExecute() {

loading.setVisibility(View.VISIBLE);

isloading = true;

super.onPreExecute();

}

protected void onPostExecute(List result) {

list.addAll(result);

loading.setVisibility(View.GONE);

adapter.notifyDataSetChanged();

isloading = false;

super.onPostExecute(result);

}

protected void onProgressUpdate(String... values) {

Toast.makeText(MainActivity.this, values[0], Toast.LENGTH_SHORT)

.show();

super.onProgressUpdate(values);

}

}.execute(null);

}

}

@Override

public void onScrollStateChanged(AbsListView view, int scrollState) {

// TODO Auto-generated method stub

switch(scrollState){

case OnScrollListener.SCROLL_STATE_FLING:

isScroll = true;

break;

case OnScrollListener.SCROLL_STATE_IDLE:

isScroll = false;

int startindex = lv_book_list.getFirstVisiblePosition();

int count = lv_book_list.getChildCount();

for(int i = 0 ; i < count ; i++){

int currentpostion = startindex + i;

final Book book = (Book) lv_book_list.getItemAtPosition(currentpostion);

final View viewchildren = lv_book_list.getChildAt(i);

ImageView icon = (ImageView) viewchildren.findViewById(R.id.icon);

Drawable drawable = ImgUtil.aimgLoader.loadDraw(book.getBpathimg(),

new ImgCallBack(){

@Override

public void imgLoaded(Drawable imgDrawable,

String imgUrl) {

ImageView ivTag = (ImageView) lv_book_list.findViewWithTag(imgUrl);

if(ivTag !=null){

ivTag.setImageDrawable(imgDrawable);

}

}

});

if(drawable != null){

icon.setImageDrawable(drawable);

}else{

icon.setImageResource(R.drawable.icon);

}

}

break;

case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:

isScroll = true;

break;

}

}

});

}

/**获取第一次显示的数据*/

private void getData(){

new AsyncTask>(){

@Override

protected List doInVoid... params) {

List listBooks = null;

try{

listBooks = BookDao.getAllBooks();

}catch(Exception e){

publishProgress("获取新书失败!");

e.printStackTrace();

}

return listBooks;

}

protected void onPreExecute() {

loading.setVisibility(View.VISIBLE);

isloading = true;

super.onPreExecute();

}

protected void onPostExecute(List result) {

list = result;

loading.setVisibility(View.GONE);

lv_book_list.setAdapter(adapter);

isloading = false;

super.onPostExecute(result);

}

protected void onProgressUpdate(String... values) {

Toast.makeText(MainActivity.this, values[0], Toast.LENGTH_SHORT)

.show();

super.onProgressUpdate(values);

}

}.execute(null);

}

private class BookListAdapter extends BaseAdapter{

@Override

public int getCount() {

// TODO Auto-generated method stub

return list.size();

}

@Override

public Object getItem(int position) {

// TODO Auto-generated method stub

return list.get(position);

}

@Override

public long getItemId(int position) {

// TODO Auto-generated method stub

return position;

}

@Override

public View getView(int position, View convertView, ViewGroup parent) {

// TODO Auto-generated method stub

View view = null;

ViewCache viewCache = null;

ViewHolder viewHolder = null;

if(convertView == null){

viewHolder = new ViewHolder();

view = View.inflate(MainActivity.this, R.layout.item, null);

viewCache = new ViewCache(view);

view.setTag(R.id.fir, viewCache);

viewHolder.name = (TextView) view.findViewById(R.id.name);

viewHolder.message = (TextView) view.findViewById(R.id.message);

viewHolder.synopsis = (TextView) view.findViewById(R.id.synopsis);

view.setTag(R.id.sec, viewHolder);

}else{

view = convertView;

viewCache = (ViewCache) view.getTag(R.id.fir);

viewHolder = (ViewHolder) view.getTag(R.id.sec);

}

Book book = list.get(position);

viewHolder.name.setText(book.getBname());

viewHolder.message.setText(book.getBmessage());

viewHolder.synopsis.setText(book.getBsynopsis());

String imgUrl = book.getBsynopsis();

ImageView imgBook = viewCache.getImgView();

imgBook.setTag(imgUrl);

if(isScroll){

imgBook.setImageResource(R.drawable.icon);

}else{

/**静止时下载网上的图片*/

Drawable drawable = ImgUtil.aimgLoader.loadDraw(imgUrl,

new ImgCallBack(){

public void imgLoaded(Drawable imgDrawable,

String imgUrl) {

ImageView ivTag = (ImageView) lv_book_list.findViewWithTag(imgUrl);

if(ivTag != null){

ivTag.setImageDrawable(imgDrawable);

}

}

});

if(drawable !=null){

imgBook.setImageDrawable(drawable);

}else{

imgBook.setImageResource(R.drawable.icon);

}

}

return view;

}

}

static class ViewHolder {

ImageView icon;

TextView name;

TextView message;

TextView synopsis;

}

}

另外涉及到的ViewCache包含view和p_w_picpathview,ImgUtil其实是AsyncImageLoader的管理器,大概这样,因为最后的这个的源码相关的解析在程序一开始就已经说明了,所以我再次看的时候大概应该也能知道吧。。。

程序其实还可以,不过因为有点杂乱,所以看得不爽,其实还有其他比较好的实现方法,但我认为写这样长一点的可以多知道其他android的知识点,再好好写下一篇的时候再写得清楚点吧~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值