首页 > 代码库 > Android 博客园客户端 (八) 下拉刷新、分页,AsyncTask

Android 博客园客户端 (八) 下拉刷新、分页,AsyncTask

一直以来,无论是博客、新闻、还是推荐用户列表。只能加载固定的数量,也没有刷新功能。

为了实现这个功能,也试过很多第三方的开源控件,如PullToRefreshListVie等。无意中发现了Google官方发布了一个新的控件(SwipeRefreshLayout),支持下拉刷新,这个控件在Google应用中都有出现过。效果也是非常的不错。

具体的使用方法及代码如下:

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2     android:layout_width="fill_parent" 3     android:layout_height="fill_parent" 4     android:orientation="vertical" > 5  6     <android.support.v4.widget.SwipeRefreshLayout 7         android:id="@+id/swipeRefreshLayoutHomeBlog" 8         android:layout_width="match_parent" 9         android:layout_height="match_parent" >10 11         <ListView12             android:id="@+id/listViewHomeBlog"13             android:layout_width="match_parent"14             android:layout_height="wrap_content" >15         </ListView>16     </android.support.v4.widget.SwipeRefreshLayout>17 18 </LinearLayout>

需要注意的一点就是SwipeRefreshLayout中只能包含一个控件。其他属性和其他Layout大体相同。

第一点,下拉刷新:

使用的话,需要在Activity或者Fragment中导入并实现android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener接口,并且要重写onRefresh()方法。

第二点,分页处理:

需要实现OnScrollListener接口,并且重写和onScrollStateChangedonScroll和两个方法。

具体代码如下

  1 package com.arlen.cnblogs.fragment;  2   3 import java.util.ArrayList;  4 import java.util.List;  5   6 import android.content.Intent;  7 import android.os.Bundle;  8 import android.support.v4.app.Fragment;  9 import android.support.v4.widget.SwipeRefreshLayout; 10 import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener; 11 import android.util.Log; 12 import android.view.LayoutInflater; 13 import android.view.View; 14 import android.view.ViewGroup; 15 import android.widget.AbsListView; 16 import android.widget.AbsListView.OnScrollListener; 17 import android.widget.AdapterView; 18 import android.widget.AdapterView.OnItemClickListener; 19 import android.widget.AdapterView.OnItemLongClickListener; 20 import android.widget.ListView; 21  22 import com.arlen.cnblogs.BlogActivity; 23 import com.arlen.cnblogs.R; 24 import com.arlen.cnblogs.adapter.BlogListAdapter; 25 import com.arlen.cnblogs.entity.Blog; 26 import com.arlen.cnblogs.task.BlogListTask; 27 import com.arlen.cnblogs.utils.AppMacros; 28 import com.arlen.cnblogs.utils.AppUtils; 29  30 public class BlogHomeFragment extends Fragment implements 31         OnItemLongClickListener, OnItemClickListener, OnRefreshListener, 32         OnScrollListener { 33     private static final String TAG = BlogHomeFragment.class.getSimpleName(); 34  35     private SwipeRefreshLayout swipeRefreshLayout; 36     private ListView listView; 37  38     private BlogListAdapter adapter; 39  40     private String path; 41     private int pageSize; 42     private int pageIndex = 1; 43     private List<Blog> blogList; 44  45     private int lastVisibleIndex; 46     private int maxVisibleIndex = 400; 47  48     private Intent intent; 49  50     public BlogHomeFragment() { 51         super(); 52     } 53  54     @Override 55     public void onCreate(Bundle savedInstanceState) { 56         super.onCreate(savedInstanceState); 57         Log.i(TAG, "onCreate"); 58     } 59  60     @Override 61     public View onCreateView(LayoutInflater inflater, ViewGroup container, 62             Bundle savedInstanceState) { 63         Log.i(TAG, "onCreateView"); 64         View rootView = inflater.inflate(R.layout.fragment_blog_home, 65                 container, false); 66         return rootView; 67     } 68  69     @Override 70     public void onViewCreated(View view, Bundle savedInstanceState) { 71         super.onViewCreated(view, savedInstanceState); 72         Log.i(TAG, "onViewCreated"); 73         initComponent(); 74         initData(); 75     } 76  77     @Override 78     public void onItemClick(AdapterView<?> parent, View view, int position, 79             long id) { 80         Log.i(TAG, "onItemClick -- " + position); 81         showBlogItem(blogList.get(position)); 82     } 83  84     @Override 85     public boolean onItemLongClick(AdapterView<?> parent, View view, 86             int position, long id) { 87         Log.i(TAG, "onItemLongClick -- " + position); 88         return false; 89     } 90  91     @Override 92     public void onRefresh() { 93         new BlogListTask(blogList, swipeRefreshLayout, adapter).execute(path, 94                 "refresh"); 95     } 96  97     @Override 98     public void onScrollStateChanged(AbsListView view, int scrollState) { 99         if (adapter.getCount() < maxVisibleIndex) {100             if (scrollState == OnScrollListener.SCROLL_STATE_IDLE101                     && lastVisibleIndex == adapter.getCount() - 1) {102 103                 pageIndex++;104                 initPath(pageIndex);105                 swipeRefreshLayout.setRefreshing(true);106                 new BlogListTask(blogList, swipeRefreshLayout, adapter)107                         .execute(path, "loadMore");108             }109         } else {110             // Toast.makeText(getActivity(), "最后一页!",111             // Toast.LENGTH_SHORT).show();112         }113     }114 115     @Override116     public void onScroll(AbsListView view, int firstVisibleItem,117             int visibleItemCount, int totalItemCount) {118         lastVisibleIndex = firstVisibleItem + visibleItemCount - 1;119     }120 121     private void initComponent() {122         swipeRefreshLayout = (SwipeRefreshLayout) this.getActivity()123                 .findViewById(R.id.swipeRefreshLayoutHomeBlog);124         swipeRefreshLayout.setOnRefreshListener(this);125         swipeRefreshLayout.setColorSchemeResources(126                 android.R.color.holo_blue_bright,127                 android.R.color.holo_green_light,128                 android.R.color.holo_orange_light,129                 android.R.color.holo_red_light);130 131         listView = (ListView) this.getActivity().findViewById(132                 R.id.listViewHomeBlog);133         listView.setOnItemClickListener(this);134         listView.setOnItemLongClickListener(this);135         listView.setOnScrollListener(this);136     }137 138     private void initData() {139         blogList = new ArrayList<Blog>();140         adapter = new BlogListAdapter(getActivity(), blogList);141         listView.setAdapter(adapter);142 143         initPath(1);144         swipeRefreshLayout.setRefreshing(true);145         new BlogListTask(blogList, swipeRefreshLayout, adapter).execute(path,146                 "init");147     }148 149     private void initPath(int pageIndex) {150         // http://wcf.open.cnblogs.com/blog/sitehome/paged/{PAGEINDEX}/{PAGESIZE}151         path = AppMacros.RECENT_BLOGS_PAGED;152         pageSize = AppMacros.PAGE_SIZE;153         path = path.replace("{PAGEINDEX}", "" + pageIndex);154         path = path.replace("{PAGESIZE}", "" + pageSize);155 156         Log.i(TAG, "pageIndex:" + pageIndex);157     }158 159     private void showBlogItem(Blog blogEntry) {160         intent = new Intent(this.getActivity(), BlogActivity.class);161 162         if (blogEntry.getAuthorAvatar() != null) {163             intent.putExtra("avatar", blogEntry.getAuthorAvatar().toString());164         } else {165             intent.putExtra("avatar", "");166         }167         intent.putExtra("title", blogEntry.getBlogTitle());168         intent.putExtra("author", blogEntry.getAuthorName());169         intent.putExtra("published",170                 AppUtils.parseDateToString(blogEntry.getPublishedDateDate()));171         intent.putExtra("id", blogEntry.getBlogId());172         intent.putExtra("link", blogEntry.getBlogTitle());173 174         startActivity(intent);175     }176 }

在之前的项目中,使用了Handler+Thread来加载数据刷新控件,但是感觉代码比较混乱。在新的版本中使用了AsyncTask来替换。具体实现如下:

 1 package com.arlen.cnblogs.task; 2  3 import java.util.ArrayList; 4 import java.util.List; 5  6 import com.arlen.cnblogs.adapter.BlogListAdapter; 7 import com.arlen.cnblogs.entity.Blog; 8 import com.arlen.cnblogs.utils.AppUtils; 9 import com.arlen.cnblogs.utils.HttpUtil;10 11 import android.os.AsyncTask;12 import android.support.v4.widget.SwipeRefreshLayout;13 14 public class BlogListTask extends AsyncTask<String, Void, Void> {15     private List<Blog> blogList;16     private List<Blog> newList = new ArrayList<Blog>();17     private SwipeRefreshLayout swipeRefreshLayout;18     private BlogListAdapter adapter;19 20     public BlogListTask(List<Blog> blogList,21             SwipeRefreshLayout swipeRefreshLayout, BlogListAdapter adapter) {22         super();23         this.blogList = blogList;24         this.swipeRefreshLayout = swipeRefreshLayout;25         this.adapter = adapter;26     }27 28     protected Void doInBackground(String... params) {29 30         newList = HttpUtil.getBlogList(params[0]);31 32         if (params[1].equals("init")) {33             blogList.addAll(newList);34         } else if (params[1].equals("refresh")) {35             newList.addAll(blogList);36             AppUtils.removeDuplicate(newList);37             blogList.clear();38             blogList.addAll(newList);39         } else if (params[1].equals("loadMore")) {40             blogList.addAll(newList);41             AppUtils.removeDuplicate(blogList);42         }43         return null;44     }45 46     @Override47     protected void onPreExecute() {48         super.onPreExecute();49         newList.clear();50     }51 52     @Override53     protected void onPostExecute(Void result) {54         super.onPostExecute(result);55 56         swipeRefreshLayout.setRefreshing(false);57         adapter.updataBlogList(blogList);58         adapter.notifyDataSetChanged();59     }60 61 }

刷新数据后可能会出现数据重复,要去除重复,首先要在类中重写equals()方法,应为要考虑到不同类型,使用了泛型方法来对User、Blog、News和Comment来进行去重。具体如下:

 1     @Override 2     public boolean equals(Object object) { 3         if (object instanceof Blog) { 4             Blog blog = (Blog) object; 5             return String.valueOf(blog.getBlogId()).equals( 6                     String.valueOf(this.getBlogId())); 7         } else { 8             return super.equals(object); 9         }10     }
1     public static <T> void removeDuplicate(List<T> list) {2         for (int i = 0; i < list.size(); i++) {3             for (int j = i + 1; j < list.size(); j++) {4                 if (list.get(i).equals(list.get(j))) {5                     list.remove(j);6                 }7             }8         }9     }

项目地址:https://github.com/ZhangTingkuo/AndroidCnblogs

Android 博客园客户端 (八) 下拉刷新、分页,AsyncTask