第一篇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進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。