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         <ListView
12             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_IDLE
101                     && 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     @Override
116     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     @Override
47     protected void onPreExecute() {
48         super.onPreExecute();
49         newList.clear();
50     }
51 
52     @Override
53     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

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。