Android AsyncTask异步加载WebAPI

之前做的程序一直存在很多问题,因为需要加载的Activity需要从网络加载数据。并没有完全正确的使用异步的方法去加载!

之前用的虽然是AsyncTask,但是在加载完成的时候还是并没有使用AsyncTask内置的方法去处理。而已傻傻的在OnCreate中处理。结果还是要等待AsyncTask加载完成后,等待OnCreate执行完成后,才load到Activity。这样子给人的第一感觉就是卡机了一样!

果断重新再写,这次的代码真是大换血。首先还是选择把带分页ListView进行封装了一下。

  1 import com.sf.campus.R;
  2
  3 import android.app.Activity;
  4 import android.os.Handler;
  5 import android.util.Log;
  6 import android.view.View;
  7 import android.view.View.OnClickListener;
  8 import android.widget.BaseAdapter;
  9 import android.widget.Button;
 10 import android.widget.ListAdapter;
 11 import android.widget.ListView;
 12 import android.widget.Toast;
 13
 14 /**
 15  * 模版化的ListView
 16  * @author Administrator
 17  *
 18  */
 19 public class ListViewPageTemplate {
 20
 21     private View loadMoreView; //用来显示加载更多的一个视图
 22     private Button loadMoreButton; //视图中的按钮
 23     private int datasize; // 记录已有数据条数
 24     private int pageindex = 1;// 页面的位置,若没有传入则默认为1
 25     private int pagesize = 3; //每页显示的数量
 26
 27     private Activity  activity;//当前的Activity
 28     private ListView myList;//当前page使用的List
 29     private ListAdapter myAdapter = null;//用来传输数据
 30     private Handler handler = new Handler();
 31
 32     private OnExcuteListener onExcuteListener;
 33     public interface OnExcuteListener{
 34         void excute();
 35     }
 36     private static final String TAG="Informacation";
 37
 38     /**
 39      * 构造函数
 40      * @param activity 上下文的Activity
 41      * @param myList 用来显示的ListView
 42      */
 43     public ListViewPageTemplate(Activity activity, ListView myList) {
 44         super();
 45         this.activity = activity;
 46         this.myList = myList;
 47         init();
 48     }
 49
 50     private void init(){
 51         Log.i(TAG, "[page] begin init");
 52         loadMoreView = activity.getLayoutInflater().inflate(R.layout.loadmore, null);
 53         loadMoreButton = (Button) loadMoreView.findViewById(R.id.loadMoreButton);
 54         myList.addFooterView(loadMoreView); //设置列表底部视图
 55         initLoadMore();
 56         Log.i(TAG, "[page] end init");
 57     }
 58
 59     /**
 60      * 点击加载更多
 61      */
 62     private void initLoadMore(){
 63         loadMoreButton.setOnClickListener(new OnClickListener() {
 64             @Override
 65             public void onClick(View arg0) {
 66                 pageindex++;
 67                 loadMoreButton.setText("正在加载中...");
 68                 handler.postDelayed(new Runnable() {
 69                      public void run() {
 70                          loadMoreData();
 71                          ((BaseAdapter) myAdapter).notifyDataSetChanged();
 72                          loadMoreButton.setText("查看更多...");  //恢复按钮文字
 73                      }
 74                  },3000);
 75             }
 76         });
 77     }
 78
 79     /**
 80      * 加载数据,更新ListView
 81      */
 82     private void loadMoreData(){
 83         int count = myAdapter.getCount();
 84         if(count+pagesize < datasize){
 85             if(onExcuteListener!= null)
 86                 onExcuteListener.excute();
 87             else{
 88                 Log.i(TAG, "[page] onExcuteListener is null");
 89             }
 90         }else{
 91             if(onExcuteListener!= null)
 92                 onExcuteListener.excute();//已经加载完成
 93             else{
 94                 Log.i(TAG, "[page] onExcuteListener is null");
 95             }
 96             ((BaseAdapter) myAdapter).notifyDataSetChanged();
 97             myList.removeFooterView(loadMoreView);
 98             alert("已加载完成!");
 99
100         }
101     }
102
103     public void alert (String msg)
104     {
105         Toast.makeText(activity.getApplicationContext(), msg, Toast.LENGTH_LONG).show();
106     }
107
108     public int getDatasize() {
109         return datasize;
110     }
111
112     public void setDatasize(int datasize) {
113         this.datasize = datasize;
114     }
115
116     public int getPageindex() {
117         return pageindex;
118     }
119
120     public void setPageindex(int pageindex) {
121         this.pageindex = pageindex;
122     }
123
124     public int getPagesize() {
125         return pagesize;
126     }
127
128     public void setPagesize(int pagesize) {
129         this.pagesize = pagesize;
130     }
131
132     public ListView getMyList() {
133         return myList;
134     }
135
136     public void setMyList(ListView myList) {
137         this.myList = myList;
138     }
139
140     public ListAdapter getMyAdapter() {
141         return myAdapter;
142     }
143
144     public void setMyAdapter(ListAdapter myAdapter) {
145         this.myAdapter = myAdapter;
146     }
147
148     public OnExcuteListener getOnExcuteListener() {
149         return onExcuteListener;
150     }
151
152     public void setOnExcuteListener(OnExcuteListener onExcuteListener) {
153         this.onExcuteListener = onExcuteListener;
154     }
155
156 }

我这里封装的ListView主要还有一个加载点击后要触发的事件,发现在类里面写个接口挺好的。

整个ListViewPageTemplate类,主要有ListView和Adapter,还有pagesize,pageindex,datasize等一些判断分页的参数。

接下来就是使用了,首先初始化一下。

1 private ListViewPageTemplate listViewTemplate = null;
2 private ListView messageCenterList;
3 private List<MessageCenter> messageCenters;//ListView显示的数据
4 messageCenterList =  (ListView) this.findViewById(R.id.listViewMessageCenter);
5 messageCenters = new ArrayList<MessageCenter>();
6 listViewTemplate = new ListViewPageTemplate(MessageCenterListActivity.this , messageCenterList);

然后当前Activity需要实现ListViewPageTemplate.OnExcuteListener接口。

 1 listViewTemplate.setOnExcuteListener(this);
 2 @Override
 3 public void excute() {
 4     MessageCenterTask task = new MessageCenterTask();
 5     try {
 6         Log.i("Informacation", "begin excute");
 7         /**
 8          * 异步处理的类
 9          */
10         task.execute();
11         Log.i("Informacation", "end excute");
12     }
13     catch (Exception e)
14     {
15         task.cancel(true);
16     }
17 }

MessageCenterTask一开始是写在别的类里面,后来发现他要用到ListView用到,ListView中的数据和Adapter。然后继承AsyncTask的类实现的doInBackground只能被调用一次,发现又写不下去了于是索性把MessageCenterTask写到Activity类的内部作为内部类存在。发现可用!哈哈!

  1 import java.util.ArrayList;
  2 import java.util.List;
  3
  4 import org.apache.http.NameValuePair;
  5 import org.apache.http.message.BasicNameValuePair;
  6
  7 import com.sf.campus.adapter.MessageCenterAdapter;
  8 import com.sf.campus.dao.MessageCenterDAO;
  9 import com.sf.campus.models.MessageCenter;
 10 import com.sf.campus.models.MessageCenterJsonBean;
 11 import com.sf.campus.utils.ConstantService;
 12 import com.sf.campus.utils.JSONHttpClient;
 13 import com.sf.campus.utils.ListViewPageTemplate;
 14 import com.sf.campus.utils.WifiService;
 15
 16 import android.app.Activity;
 17 import android.os.AsyncTask;
 18 import android.os.Bundle;
 19
 20 import android.util.Log;
 21 import android.view.LayoutInflater;
 22 import android.view.View;
 23 import android.view.View.OnClickListener;
 24
 25 import android.widget.BaseAdapter;
 26 import android.widget.LinearLayout;
 27 import android.widget.ListAdapter;
 28 import android.widget.ListView;
 29 import android.widget.TextView;
 30 import android.widget.Toast;
 31
 32 public class MessageCenterListActivity extends Activity  implements ListViewPageTemplate.OnExcuteListener{
 33
 34     private ListView messageCenterList;
 35     private ListAdapter adapter;
 36
 37     private ListViewPageTemplate listViewTemplate = null;
 38
 39     private List<MessageCenter> messageCenters;//ListView显示的数据
 40     private boolean isFirstPage = true;
 41
 42     private static final String TAG="Informacation";
 43
 44     @Override
 45     protected void onCreate(Bundle savedInstanceState) {
 46         Log.i(TAG, "onCreate");
 47         super.onCreate(savedInstanceState);
 48         setContentView(R.layout.messagecenter_list);
 49         messageCenterList =  (ListView) this.findViewById(R.id.listViewMessageCenter);
 50         messageCenters = new ArrayList<MessageCenter>();
 51         /**
 52          * 与界面相关包含ListView实现一些分页功能
 53          */
 54         listViewTemplate = new ListViewPageTemplate(MessageCenterListActivity.this , messageCenterList);
 55
 56         Log.i(TAG, "对象已经初始化完成!");
 57
 58     }
 59
 60     @Override
 61     protected void onStart() {
 62         super.onStart();
 63         if (new WifiService(MessageCenterListActivity.this).isNetworkConnected() == true) {
 64             Log.e("Informacation", "网络加载");
 65             excute();
 66         } else {
 67             Log.e("Informacation", "本地加载");
 68             // 如果没有网络则直接加载本地数据
 69             loadDataForLocal();
 70         }
 71         listViewTemplate.setOnExcuteListener(this);
 72         setTitle();
 73         addTitleBack();
 74     }
 75
 76     public void alert (String msg)
 77     {
 78         Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
 79     }
 80
 81
 82     /**
 83      * 加载本地数据
 84      */
 85     public void loadDataForLocal() {
 86         MessageCenterDAO dao = new MessageCenterDAO(getApplicationContext());
 87         List<MessageCenter> mcs = dao.getScrollData(0, 8);
 88
 89         if( messageCenters != null ){
 90             listViewTemplate.setDatasize(Integer.valueOf(mcs.get(0).getDatasize()));
 91             adapter = new MessageCenterAdapter(LayoutInflater.from(MessageCenterListActivity.this), mcs);
 92             listViewTemplate.setMyAdapter(adapter);
 93             listViewTemplate.getMyList().setAdapter(listViewTemplate.getMyAdapter());
 94         }else{
 95             Log.i(TAG, "[Method:loadDataForLocal] messageCenterList is null");
 96         }
 97     }
 98
 99
100     /**
101      * 保存到本地
102      * @param messageCenters
103      */
104     public void save(List<MessageCenter> messageCenters){
105         MessageCenterDAO dao = new MessageCenterDAO(getApplicationContext());
106         dao.deleteAll();
107         for(MessageCenter mc : messageCenters){
108             dao.save(mc);
109         }
110     }
111
112     @Override
113     public void excute() {
114         MessageCenterTask task = new MessageCenterTask();
115         try {
116             Log.i("Informacation", "begin excute");
117             /**
118              * 提供常用CURD及数据获取的类
119              */
120             task.execute();
121             Log.i("Informacation", "end excute");
122         }
123         catch (Exception e)
124         {
125             task.cancel(true);
126         }
127     }
128
129     /**
130      * adapter的一些字段
131      * @author Administrator
132      *
133      */
134     public static class MessageCenterRowHolder {
135         public TextView messageCenterId, messageCenterTitle;
136         public MessageCenter messageCenter;
137     }
138
139     /**
140      * 设置标题
141      */
142     private void setTitle(){
143         TextView tv = (TextView) this.findViewById(R.id.title_text);
144         tv.setText("消息中心");
145     }
146
147     /**
148      * 返回事件
149      */
150     private void addTitleBack(){
151         LinearLayout layout= (LinearLayout) this.findViewById(R.id.title_back);
152         layout.setOnClickListener(new OnClickListener() {
153
154             @Override
155             public void onClick(View arg0) {
156                 MessageCenterListActivity.this.finish();
157             }
158         });
159     }
160
161     /**
162      *
163      * @author Administrator
164      *
165      */
166     class MessageCenterTask  extends AsyncTask<String, String, List<MessageCenter>>{
167
168         String URL= ConstantService.HEAD + ConstantService.SCHOOL + ConstantService.MESSAGECENTER_SERVICE_URL;
169
170         private List<NameValuePair> createNameValuePairs(){
171             Log.i(TAG,  "userId=" + String.valueOf( ConstantService.userID )  +
172                         "pageIndex="+ String.valueOf( listViewTemplate.getPageindex()) +
173                         "pageSize" + String.valueOf(listViewTemplate.getPagesize()));
174             List<NameValuePair> list = new ArrayList<NameValuePair>();
175             NameValuePair p1 = new BasicNameValuePair("userId", String.valueOf( ConstantService.userID ) );
176             NameValuePair p2 = new BasicNameValuePair("pageIndex", String.valueOf( listViewTemplate.getPageindex() ) );
177             NameValuePair p3 = new BasicNameValuePair("pageSize" , String.valueOf(listViewTemplate.getPagesize()));
178             NameValuePair p4 = new BasicNameValuePair("format" , "json");
179             list.add(p1);
180             list.add(p2);
181             list.add(p3);
182             list.add(p4);
183             return list;
184         }
185
186         /**
187          * 这里的Integer参数对应AsyncTask中的第一个参数
188          * 这里的String返回值对应AsyncTask的第三个参数
189          * 该方法并不运行在UI线程当中,主要用于异步操作,所有在该方法中不能对UI当中的空间进行设置和修改
190          * 但是可以调用publishProgress方法触发onProgressUpdate对UI进行操作
191          */
192         @Override
193         protected List<MessageCenter> doInBackground(String... arg0) {
194             Log.i(TAG, "Task Start");
195             List<NameValuePair> pairs =  createNameValuePairs();
196             List<MessageCenter> mcs= new ArrayList<MessageCenter>();
197             JSONHttpClient client= new JSONHttpClient();
198             MessageCenterJsonBean result= client.Get(URL, pairs, MessageCenterJsonBean.class );
199             //存储页面的大小
200             listViewTemplate.setDatasize(result.getTotal());
201             for(int i=0; i<result.getRows().size(); i++){
202                 MessageCenter messageCenter = new MessageCenter();
203                 messageCenter.setID(result.getRows().get(i).getID());
204                 messageCenter.setTitle(result.getRows().get(i).getTitle());
205                 messageCenter.setContent(result.getRows().get(i).getContent());
206                 mcs.add(messageCenter);
207             }
208             Log.i(TAG, "Task End");
209             return  mcs;
210
211         }
212
213         /**
214          * 这里的String参数对应AsyncTask中的第三个参数(也就是接收doInBackground的返回值)
215          * 在doInBackground方法执行结束之后在运行,并且运行在UI线程当中 可以对UI空间进行设置
216          */
217         @Override
218         protected void onPostExecute(List<MessageCenter> result) {
219             loadDataForNet(result);
220             super.onPostExecute(result);
221         }
222
223         /**
224          * 加载网络数据
225          * @param result
226          */
227         private void loadDataForNet(List<MessageCenter> result) {
228             if(result != null)
229             {
230                 //若是第一页则保存到本地
231                 if(isFirstPage){
232                     Log.i(TAG, "第一次加载!");
233                     save(result);
234                     messageCenters.clear();
235                     messageCenters.addAll(result);
236                     adapter = new MessageCenterAdapter(LayoutInflater.from(MessageCenterListActivity.this),  messageCenters);
237                     listViewTemplate.setMyAdapter(adapter);
238                     listViewTemplate.getMyList().setAdapter(listViewTemplate.getMyAdapter());
239                     //listViewTemplate.setMyAdapter(adapter);
240                     isFirstPage = false;
241                 }else{
242                     Log.i(TAG, "不是第一次加载!更新!");
243                     messageCenters.addAll(result);
244                     ((BaseAdapter) adapter).notifyDataSetChanged();
245                 }
246
247             }
248             else
249             {
250                 Log.i(TAG, "[Method:loadDataForNetFirst] messageCenterList is null");
251             }
252         }
253     }
254
255 }

算是实现了,真是不容易啊!感谢DevinZhang博主的一篇文章android AsyncTask介绍

从其中学到了很多新的知识点,非常的感谢!

Android AsyncTask异步加载WebAPI

时间: 2025-01-16 06:17:37

Android AsyncTask异步加载WebAPI的相关文章

Android学习笔记—第六章 Asynctask异步加载

第六章 Asynctask 异步加载 1.好处:不需要创建线程就可管理线程 缺点:步骤多 2.步骤: (1)创建一个类继承Asynctask<xxx,xxx,xxx>; 三个泛型参数: 第一个:决定了execute()方法的传入值类型,决定了doInBackground()方法的传入值类型 第二个:决定了publishProgress()方法的传入值类型,决定了onProgressUpdate()方法的传入值类型 第三个:决定了doInBackground()方法的返回值类型,决定了onPos

Android图片异步加载之Android-Universal-Image-Loader

将近一个月没有更新博客了,由于这段时间以来准备毕业论文等各种事务缠身,一直没有时间和精力沉下来继续学习和整理一些东西.最近刚刚恢复到正轨,正好这两天看了下Android上关于图片异步加载的开源项目,就顺便整理记录下来,作为这一个多月来博客的重新开火做饭吧.从今天起我会陆续恢复博客的更新,也希望大家继续支持. 今天要介绍的是Github上一个使用非常广泛的图片异步加载库Android-Universal-Image-Loader,该项目的功能十分强大,可以说是我见过的目前功能最全.性能最优的图片异

android listview 异步加载图片并防止错位

网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 convertView 不会出现错位现象, 重用 convertView 但没有异步操作也不会有问题. 我简单分析一下: 当重用 convertView 时,最初一屏显示 7 条记录, getView 被调用 7 次,创建了 7 个 convertView. 当 Item1 划出屏幕, Item8 进入屏幕时,这时没有为 Item8 创建新的 view 实例, Ite

Android图片异步加载之Android-Universal-Image-Loader类库的使用

Android开发中我们会经常遇到图片过多或操作不当造成Out of Memory异常,有时虽然是解决了这个问题但却会影响程序的运行效率,例如:当用户在快速滑动滚动条的过程中,我们程序在仍在艰难的加载服务器端的图片,这样给用户造成了极不好的体验.其实网络上关于图片的异步加载和缓存的讲解很多,但是其实,写一个这方面的程序还是比较麻烦的,要考虑多线程,缓存,内存溢出等很多方面,针对这一广大开发者都会遇到的问题,一些牛人们已经帮我们解决了这一问题,今天我为大家介绍一款很流行的开源类库,可以很很好的解决

android listview 异步加载图片并防止错位+双缓存

网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 convertView 不会出现错位现象, 重用 convertView 但没有异步操作也不会有问题. 我简单分析一下: 当重用 convertView 时,最初一屏显示 7 条记录, getView 被调用 7 次,创建了 7 个 convertView. 当 Item1 划出屏幕, Item8 进入屏幕时,这时没有为 Item8 创建新的 view 实例, Ite

Android图片异步加载之Android-Universal-Image-Loader(转)

今天要介绍的是Github上一个使用非常广泛的图片异步加载库Android-Universal-Image-Loader,该项目的功能十分强大,可以说是我见过的目前功能最全.性能最优的图片异步加载解决方案.做Android的同学都知道,Android加载大量图片时,由于系统分配给图片加载的内存大小有限,所以,如果加载图片量非常大的话容易报OOM异常,关于这个异常已经有不少解决方案了,我就不赘述.下面就简要介绍下这个开源项目的主要功能和使用: 一.功能概要 多线程图片加载: 灵活更改ImageLo

又优化了一下 Android ListView 异步加载图片

写这篇文章并不是教大家怎么样用listview异步加载图片,因为这样的文章在网上已经有很多了,比如这位仁兄写的就很好: http://www.iteye.com/topic/685986 我也是因为看了这篇文章而受到了启发. 先说说这篇文章的优点把,开启线程异步加载图片,然后刷新UI显示图片,而且通过弱引用缓存网络加载的图片,节省了再次连接网络的开销. 这样做无疑是非常可取的方法,但是加载图片时仍然会感觉到轻微的卡屏现象,特别是listview里的item在进行快速滑动的时候. 我找了一下原因,

android listview 异步加载图片并防止错位 解决办法

网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 convertView 不会出现错位现象, 重用 convertView 但没有异步操作也不会有问题. 我简单分析一下: 当重用 convertView 时,最初一屏显示 7 条记录, getView 被调用 7 次,创建了 7 个 convertView. 当 Item1 划出屏幕, Item8 进入屏幕时,这时没有为 Item8 创建新的 view 实例, Ite

自己动手写android图片异步加载库(二)

在<自己动手写android图片异步加载库>系列的第一篇文章中,主要是学习了使用ReferenceQueue来实现一个内存缓存.在这篇文章中主要是介绍在下载很多图片是怎么控制线程和队列.在这版代码里,加入信号量和队列,可以控制下载任务的顺序.可以控制暂停和结束. 代码A:ImageLoader.java /** * 图片加载工具类 * * @author qingtian * @blog http://blog.csdn.net/bingoSpunky */ @SuppressLint(&qu