第一篇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>
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的知识点,再好好写下一篇的时候再写得清楚点吧~
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。