ListView结合软引用和懒加载

发布时间:2020-06-18 14:53:07 作者:dongdong200514
来源:网络 阅读:1119

第一篇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进行显示,估计需要适当的修改,具体待会儿写一下,所以程序本身只是提供一个思路,如何解耦估计到时可以在这个程序基础上修改。。。因为跟着程序写得同时也在思考程序是怎么的流程,理解并记下来免得忘了。


程序:

豆瓣的网址:http://book.douban.com/lates

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

<li>
    <div>
        <h3>        </h3>
        <p>        </p>
        <p>        </p>
    </div>
    <a href>    <img src=></img>    </a>
</li>

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

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

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


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

public class BookDao {
    public static List<Book> getAllBooks() throws Exception{
        List<Book> list = new ArrayList<Book>();
        URL url = new URL("http://book.douban.com/latest");
        URLConnection conn = url.openConnection();
        Source source = new Source(conn);
        List<Element>elList = source.getAllElements("li");
        for(Element e:elList){
            List<Element> 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<String , SoftReference<Drawable>>();通过图像地址唯一标识图片作为Key,通过软引用图像。loadDraw(final String imgUrl,final ImgCallBack imgCallBack)判断是否存在缓存图片。如果没有缓冲,即开启线程去下载图片,同时将当前的图片放入到存放缓存图片的HashMap中。

public class MainActivity extends Activity {
                                                                                   
    private List<Book> 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<Book>();
        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<Void ,String ,List<Book>>(){
                        @Override
                        protected List<Book> doInVoid...  params) {
                            List<Book> 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<Book> 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<Void ,String ,List<Book>>(){
            @Override
            protected List<Book> doInVoid...  params) {
                List<Book> 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<Book> 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的知识点,再好好写下一篇的时候再写得清楚点吧~




推荐阅读:
  1. ListView设置headerview和footerview
  2. ListView结合Filter遇到的问题摘记

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

缓存 软引用 listview

上一篇:AD不能复制提示目标主要名称不正确

下一篇:DOM在JavaScript的应用

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》