第一篇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标签如下设置:

  • 根据标签我们可以设置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的知识点,再好好写下一篇的时候再写得清楚点吧~