• 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介绍

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

  • 相关阅读:
    TVM性能评估分析(三)
    TVM性能评估分析(二)
    TVM性能评估分析(一)
    飞腾上实体名单?
    华为不造车,广汽合作智能驾驶
    异构计算编程
    服务器硬件层次架构
    为何说要多用组合少用继承?如何决定该用组合还是继承?
    极客时间学习
    如果学不好编程,就看看这个吧
  • 原文地址:https://www.cnblogs.com/chenjianxiang/p/3874366.html
Copyright © 2020-2023  润新知