第一篇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的知识点,再好好写下一篇的时候再写得清楚点吧~
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。