Android的异步加载AsyncTask方式Http请求的封装(改进版)

相对于上次的Handler + Thread而言,本次的封装,改进之处在于:

  1. 改变了使用的方式,不再需要另写一个父类供子类继承
  2. 新增了网络请求超时的处理
  3. 增加了加载时的处理
  4. 极大简化了使用的繁琐度
一、回调接口OnRequest

package com.jandar.wzj.http;

/**
 * 注:该接口中的所有方法都是在主线程中调用的
 * @author wzj
 * @version 2014-12-5 上午11:31:19
 */
public interface OnRequest<T> {
	
	/**
	 * 当前无网络时回调该方法,回调后,该接口的其他方法都不会被调用
	 */
	void onNoInternet();
	
	/**
	 * 开始加载时调用,一般在此处放入加载进度条
	 */
	void onStartLoad();
	
	/**
	 * 只有加载成功时,才会调用该方法
	 * @param result: 返回该次请求结果
	 */
	void onComplete(T result);
	
	/**
	 * 超时时调用该方法
	 */
	void onTimeOut();
	
	/**
	 * 加载出错时调用该方法
	 */
	void onError();
	
}

二、枚举类State,用来标示请求方式

package com.jandar.wzj.http;

/**
 * 表示网络请求的方式
 * @author wzj
 * @version 2014-12-5 上午11:40:51
 */
public enum State {

	GET,
	
	POST,
	
}

三、Http请求的操作类AsyncHttp

package com.jandar.wzj.http.async;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;

import com.jandar.wzj.exception.JDException;
import com.jandar.wzj.http.OnRequest;
import com.jandar.wzj.http.State;

/**
 * 自定义类,处理get post请求、后需添加
 * 
 * @author wzj
 * @version 2014-12-2 下午3:36:06
 */
public class AsyncHttp {

	private Context context;

	private HttpClient client;

	/**
	 * 默认超时时间为 8 秒
	 */
	private Integer timeOut = 8000;

	/**
	 * 默认请求方式为 Get
	 */
	private State state = State.GET;

	AsyncHttp(Context context) {
		this(context, null, null);
	}

	AsyncHttp(Context context, Integer timeOut) {
		this(context, timeOut, null);
	}

	AsyncHttp(Context context, State state) {
		this(context, null, state);
	}

	AsyncHttp(Context context, Integer timeOut, State state) {
		client = new DefaultHttpClient();
		this.context = context;
		if (timeOut != null) {
			this.timeOut = timeOut;
		}
		if (state != null) {
			this.state = state;
		}
	}

	void execute(String url, OnRequest<String> request) {
		execute(url, null, request);
	}

	void execute(String url, ArrayList<BasicNameValuePair> list, final OnRequest<String> request) {
		if (request == null) {
			new JDException("回调接口为 null");
			return;
		}

		if (!isConnected(context)) {
			request.onNoInternet();
			return;
		}

		final Async async = new Async(request);
		async.setParams(list);
		async.execute(url);
	}

	void close() {
		if(client != null){
			client.getConnectionManager().shutdown();
		}
	}
	
	private class Async extends AsyncTask<String, Void, String> {

		private OnRequest<String> request;
		private ArrayList<BasicNameValuePair> list;

		private boolean isTimeOut = false;
		private boolean isFinished = false;
		
		Async(OnRequest<String> request) {
			this.request = request;
		}

		@Override
		protected String doInBackground(String... params) {
			try {
				Timer timer = new Timer();
				timer.schedule(new TimerTask() {

					@Override
					public void run() {
						if(!isFinished){
							isTimeOut = true;
							Async.this.cancel(true);
						}
					}

				}, timeOut);
				
				String result = null;
				HttpResponse response;
				switch (state) {
				case GET:
					HttpGet get = new HttpGet(params[0]);
					response = client.execute(get);
					InputStream is = response.getEntity().getContent();
					ByteArrayOutputStream baos = new ByteArrayOutputStream();
					byte[] buffer = new byte[1024];
					int index = -1;
					while((index = is.read(buffer)) != -1){
						baos.write(buffer, 0, index);
					}
					result = baos.toString();
					baos.close();
					is.close();
					break;
				case POST:
					HttpPost post = new HttpPost(params[0]);
					if(list != null && list.size() > 0){
						post.setEntity(new UrlEncodedFormEntity(list, HTTP.UTF_8));
					}
					response = client.execute(post);
					result = EntityUtils.toString(response.getEntity());
					break;
				}
				return result;
			} catch (Exception e) {
				cancel(true);
				return null;
			}
		}

		@Override
		protected void onPreExecute() {
			request.onStartLoad();
		}

		@Override
		protected void onPostExecute(String result) {
			if(!isTimeOut && !isFinished){
				isFinished = true;
				request.onComplete(result);
			}
		}

		@Override
		protected void onCancelled(String result) {
			//超时加载
			if(isTimeOut && !isFinished){
				isFinished = true;
				request.onTimeOut();
			}
			
			//加载出错
			if(!isTimeOut){
				isFinished = true;
				request.onError();
			}
		}

		private void setParams(ArrayList<BasicNameValuePair> list) {
			this.list = list;
		}

	}

	private boolean isConnected(Context context) {
		ConnectivityManager cm = (ConnectivityManager) context.getSystemService("connectivity");
		if (cm != null) {
			NetworkInfo[] info = cm.getAllNetworkInfo();
			if (info != null) {
				for (int i = 0; i < info.length; ++i) {
					if (info[i].getState() == NetworkInfo.State.CONNECTED) {
						return true;
					}
				}
			}
		}
		return false;
	}
}


四、AsyncHttp的代理类AsyncServices,对AsyncHttp进封装

package com.jandar.wzj.http.async;

import java.util.ArrayList;

import org.apache.http.message.BasicNameValuePair;

import android.app.ProgressDialog;
import android.content.Context;

import com.jandar.wzj.http.OnRequest;
import com.jandar.wzj.http.State;
import com.jandar.wzj.util.T;

/**
 * 该类作为AsyncHttp的代理类,封装了Async的方法,并实现了自己的一些处理
 * 对外提供了OnResult接口
 * @author wzj
 * @version 2014-12-8 上午9:18:49
 */
public class AsyncServices {

	private AsyncHttp async;
	
	private Context context;
	
	private ProgressDialog dialog;
	
	private OnRequest<String> listener;
	
	public interface OnResult<R> {
		void onResult(R t);
	}

	public AsyncServices(Context context) {
		async = new AsyncHttp(context);
		init(context);
	}

	public AsyncServices(Context context, Integer timeOut) {
		async = new AsyncHttp(context, timeOut);
		init(context);
	}

	public AsyncServices(Context context, State state) {
		async = new AsyncHttp(context, state);
		init(context);
	}

	public AsyncServices(Context context, Integer timeOut, State state) {
		async = new AsyncHttp(context, timeOut, state);
		init(context);
	}
	
	
	
	private void init(Context context) {
		this.context = context;
	}
	
	public void execute(String url, OnResult<String> result) {
		async.execute(url, this.listener == null ? new Request(result) : this.listener);
	}
	
	public void execute(String url, ArrayList<BasicNameValuePair> list, OnResult<String> result) {
		async.execute(url, list, this.listener == null ? new Request(result) : this.listener);
	}
	
	/**
	 * 改变加载进度条可重写此方法
	 * @return
	 */
	public ProgressDialog getLoadDialog() {
		return null;
	}
	
	/**
	 * 可重写此方法来处理请求信息的回调
	 * @return
	 */
	public void setOnRequest(OnRequest<String> listener) {
		this.listener = listener;
	}
	
	/**
	 * 关闭HttpClient,该类不会使用时调用
	 */
	public void close() {
		async.close();
	}
	
	private class Request implements OnRequest<String> {

		private OnResult<String> listener;
		
		Request(OnResult<String> listener){
			this.listener = listener;
		}
		
		@Override
		public void onNoInternet() {
			T("当前无网络");
		}

		@Override
		public void onStartLoad() {
			if((dialog = getLoadDialog()) == null){
				dialog = new ProgressDialog(context, ProgressDialog.THEME_HOLO_LIGHT);
				dialog.setMessage("正在加载,请稍后..");
				dialog.setCanceledOnTouchOutside(false);
			}
			dialog.show();
		}

		@Override
		public void onComplete(String result) {
			listener.onResult(result);
			dismissDialog();
		}

		@Override
		public void onTimeOut() {
			T("加载超时,请稍后再试");
			dismissDialog();
		}

		@Override
		public void onError() {
			T("网络错误,请稍后再试");
			dismissDialog();
		}
		
		private void dismissDialog() {
			if(dialog != null && dialog.isShowing()){
				dialog.dismiss();
			}
		}
		
		private void T(String message){
			Toast.makeText(context, message, Toast.LENGTH_SHORT).show;
		}
		
	}
	
}

五、封装完毕,测试类MainActivity

package com.jandar.wzj.test;

import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.widget.TextView;

import com.jandar.wzj.R;
import com.jandar.wzj.http.State;
import com.jandar.wzj.http.async.AsyncServices;
import com.jandar.wzj.http.async.AsyncServices.OnResult;

/**
 * @author wzj
 * @version 2014-12-5 下午5:20:56
 */
public class MainActivity extends Activity {

	private TextView text;
	private static final String URL = "http://www.baidu.com";
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);
		
		text = (TextView) findViewById(R.id.text);
		
		AsyncServices services = new AsyncServices(this, State.POST);
		
		services.execute(URL, new OnResult<String>(){

			@Override
			public void onResult(String t) {
				text.setText(t);
			}
			
		});
		
	}
	
}


注: 1. 若改变进度条样式,可重写AsyncServices类的getLoadDialog()方法

 2. 若自定义对Http请求各种状态的处理,可调用services的setOnRequest()方法

 3. 后续继续优化,调整,欢迎指正...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值