Android AsyncTask异步加载WebAPI

时间:2023-03-09 07:01:10
Android AsyncTask异步加载WebAPI

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

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

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

 import com.sf.campus.R;

 import android.app.Activity;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Toast; /**
* 模版化的ListView
* @author Administrator
*
*/
public class ListViewPageTemplate { private View loadMoreView; //用来显示加载更多的一个视图
private Button loadMoreButton; //视图中的按钮
private int datasize; // 记录已有数据条数
private int pageindex = 1;// 页面的位置,若没有传入则默认为1
private int pagesize = 3; //每页显示的数量 private Activity activity;//当前的Activity
private ListView myList;//当前page使用的List
private ListAdapter myAdapter = null;//用来传输数据
private Handler handler = new Handler(); private OnExcuteListener onExcuteListener;
public interface OnExcuteListener{
void excute();
}
private static final String TAG="Informacation"; /**
* 构造函数
* @param activity 上下文的Activity
* @param myList 用来显示的ListView
*/
public ListViewPageTemplate(Activity activity, ListView myList) {
super();
this.activity = activity;
this.myList = myList;
init();
} private void init(){
Log.i(TAG, "[page] begin init");
loadMoreView = activity.getLayoutInflater().inflate(R.layout.loadmore, null);
loadMoreButton = (Button) loadMoreView.findViewById(R.id.loadMoreButton);
myList.addFooterView(loadMoreView); //设置列表底部视图
initLoadMore();
Log.i(TAG, "[page] end init");
} /**
* 点击加载更多
*/
private void initLoadMore(){
loadMoreButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
pageindex++;
loadMoreButton.setText("正在加载中...");
handler.postDelayed(new Runnable() {
public void run() {
loadMoreData();
((BaseAdapter) myAdapter).notifyDataSetChanged();
loadMoreButton.setText("查看更多..."); //恢复按钮文字
}
},3000);
}
});
} /**
* 加载数据,更新ListView
*/
private void loadMoreData(){
int count = myAdapter.getCount();
if(count+pagesize < datasize){
if(onExcuteListener!= null)
onExcuteListener.excute();
else{
Log.i(TAG, "[page] onExcuteListener is null");
}
}else{
if(onExcuteListener!= null)
onExcuteListener.excute();//已经加载完成
else{
Log.i(TAG, "[page] onExcuteListener is null");
}
((BaseAdapter) myAdapter).notifyDataSetChanged();
myList.removeFooterView(loadMoreView);
alert("已加载完成!"); }
} public void alert (String msg)
{
Toast.makeText(activity.getApplicationContext(), msg, Toast.LENGTH_LONG).show();
} public int getDatasize() {
return datasize;
} public void setDatasize(int datasize) {
this.datasize = datasize;
} public int getPageindex() {
return pageindex;
} public void setPageindex(int pageindex) {
this.pageindex = pageindex;
} public int getPagesize() {
return pagesize;
} public void setPagesize(int pagesize) {
this.pagesize = pagesize;
} public ListView getMyList() {
return myList;
} public void setMyList(ListView myList) {
this.myList = myList;
} public ListAdapter getMyAdapter() {
return myAdapter;
} public void setMyAdapter(ListAdapter myAdapter) {
this.myAdapter = myAdapter;
} public OnExcuteListener getOnExcuteListener() {
return onExcuteListener;
} public void setOnExcuteListener(OnExcuteListener onExcuteListener) {
this.onExcuteListener = onExcuteListener;
} }

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

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

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

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

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

 listViewTemplate.setOnExcuteListener(this);
@Override
public void excute() {
MessageCenterTask task = new MessageCenterTask();
try {
Log.i("Informacation", "begin excute");
/**
* 异步处理的类
*/
task.execute();
Log.i("Informacation", "end excute");
}
catch (Exception e)
{
task.cancel(true);
}
}

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

 import java.util.ArrayList;
import java.util.List; import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair; import com.sf.campus.adapter.MessageCenterAdapter;
import com.sf.campus.dao.MessageCenterDAO;
import com.sf.campus.models.MessageCenter;
import com.sf.campus.models.MessageCenterJsonBean;
import com.sf.campus.utils.ConstantService;
import com.sf.campus.utils.JSONHttpClient;
import com.sf.campus.utils.ListViewPageTemplate;
import com.sf.campus.utils.WifiService; import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle; import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener; import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast; public class MessageCenterListActivity extends Activity implements ListViewPageTemplate.OnExcuteListener{ private ListView messageCenterList;
private ListAdapter adapter; private ListViewPageTemplate listViewTemplate = null; private List<MessageCenter> messageCenters;//ListView显示的数据
private boolean isFirstPage = true; private static final String TAG="Informacation"; @Override
protected void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.messagecenter_list);
messageCenterList = (ListView) this.findViewById(R.id.listViewMessageCenter);
messageCenters = new ArrayList<MessageCenter>();
/**
* 与界面相关包含ListView实现一些分页功能
*/
listViewTemplate = new ListViewPageTemplate(MessageCenterListActivity.this , messageCenterList); Log.i(TAG, "对象已经初始化完成!"); } @Override
protected void onStart() {
super.onStart();
if (new WifiService(MessageCenterListActivity.this).isNetworkConnected() == true) {
Log.e("Informacation", "网络加载");
excute();
} else {
Log.e("Informacation", "本地加载");
// 如果没有网络则直接加载本地数据
loadDataForLocal();
}
listViewTemplate.setOnExcuteListener(this);
setTitle();
addTitleBack();
} public void alert (String msg)
{
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
} /**
* 加载本地数据
*/
public void loadDataForLocal() {
MessageCenterDAO dao = new MessageCenterDAO(getApplicationContext());
List<MessageCenter> mcs = dao.getScrollData(0, 8); if( messageCenters != null ){
listViewTemplate.setDatasize(Integer.valueOf(mcs.get(0).getDatasize()));
adapter = new MessageCenterAdapter(LayoutInflater.from(MessageCenterListActivity.this), mcs);
listViewTemplate.setMyAdapter(adapter);
listViewTemplate.getMyList().setAdapter(listViewTemplate.getMyAdapter());
}else{
Log.i(TAG, "[Method:loadDataForLocal] messageCenterList is null");
}
} /**
* 保存到本地
* @param messageCenters
*/
public void save(List<MessageCenter> messageCenters){
MessageCenterDAO dao = new MessageCenterDAO(getApplicationContext());
dao.deleteAll();
for(MessageCenter mc : messageCenters){
dao.save(mc);
}
} @Override
public void excute() {
MessageCenterTask task = new MessageCenterTask();
try {
Log.i("Informacation", "begin excute");
/**
* 提供常用CURD及数据获取的类
*/
task.execute();
Log.i("Informacation", "end excute");
}
catch (Exception e)
{
task.cancel(true);
}
} /**
* adapter的一些字段
* @author Administrator
*
*/
public static class MessageCenterRowHolder {
public TextView messageCenterId, messageCenterTitle;
public MessageCenter messageCenter;
} /**
* 设置标题
*/
private void setTitle(){
TextView tv = (TextView) this.findViewById(R.id.title_text);
tv.setText("消息中心");
} /**
* 返回事件
*/
private void addTitleBack(){
LinearLayout layout= (LinearLayout) this.findViewById(R.id.title_back);
layout.setOnClickListener(new OnClickListener() { @Override
public void onClick(View arg0) {
MessageCenterListActivity.this.finish();
}
});
} /**
*
* @author Administrator
*
*/
class MessageCenterTask extends AsyncTask<String, String, List<MessageCenter>>{ String URL= ConstantService.HEAD + ConstantService.SCHOOL + ConstantService.MESSAGECENTER_SERVICE_URL; private List<NameValuePair> createNameValuePairs(){
Log.i(TAG, "userId=" + String.valueOf( ConstantService.userID ) +
"pageIndex="+ String.valueOf( listViewTemplate.getPageindex()) +
"pageSize" + String.valueOf(listViewTemplate.getPagesize()));
List<NameValuePair> list = new ArrayList<NameValuePair>();
NameValuePair p1 = new BasicNameValuePair("userId", String.valueOf( ConstantService.userID ) );
NameValuePair p2 = new BasicNameValuePair("pageIndex", String.valueOf( listViewTemplate.getPageindex() ) );
NameValuePair p3 = new BasicNameValuePair("pageSize" , String.valueOf(listViewTemplate.getPagesize()));
NameValuePair p4 = new BasicNameValuePair("format" , "json");
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);
return list;
} /**
* 这里的Integer参数对应AsyncTask中的第一个参数
* 这里的String返回值对应AsyncTask的第三个参数
* 该方法并不运行在UI线程当中,主要用于异步操作,所有在该方法中不能对UI当中的空间进行设置和修改
* 但是可以调用publishProgress方法触发onProgressUpdate对UI进行操作
*/
@Override
protected List<MessageCenter> doInBackground(String... arg0) {
Log.i(TAG, "Task Start");
List<NameValuePair> pairs = createNameValuePairs();
List<MessageCenter> mcs= new ArrayList<MessageCenter>();
JSONHttpClient client= new JSONHttpClient();
MessageCenterJsonBean result= client.Get(URL, pairs, MessageCenterJsonBean.class );
//存储页面的大小
listViewTemplate.setDatasize(result.getTotal());
for(int i=0; i<result.getRows().size(); i++){
MessageCenter messageCenter = new MessageCenter();
messageCenter.setID(result.getRows().get(i).getID());
messageCenter.setTitle(result.getRows().get(i).getTitle());
messageCenter.setContent(result.getRows().get(i).getContent());
mcs.add(messageCenter);
}
Log.i(TAG, "Task End");
return mcs; } /**
* 这里的String参数对应AsyncTask中的第三个参数(也就是接收doInBackground的返回值)
* 在doInBackground方法执行结束之后在运行,并且运行在UI线程当中 可以对UI空间进行设置
*/
@Override
protected void onPostExecute(List<MessageCenter> result) {
loadDataForNet(result);
super.onPostExecute(result);
} /**
* 加载网络数据
* @param result
*/
private void loadDataForNet(List<MessageCenter> result) {
if(result != null)
{
//若是第一页则保存到本地
if(isFirstPage){
Log.i(TAG, "第一次加载!");
save(result);
messageCenters.clear();
messageCenters.addAll(result);
adapter = new MessageCenterAdapter(LayoutInflater.from(MessageCenterListActivity.this), messageCenters);
listViewTemplate.setMyAdapter(adapter);
listViewTemplate.getMyList().setAdapter(listViewTemplate.getMyAdapter());
//listViewTemplate.setMyAdapter(adapter);
isFirstPage = false;
}else{
Log.i(TAG, "不是第一次加载!更新!");
messageCenters.addAll(result);
((BaseAdapter) adapter).notifyDataSetChanged();
} }
else
{
Log.i(TAG, "[Method:loadDataForNetFirst] messageCenterList is null");
}
}
} }

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

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