读书人

Android兑现异步处理 - HTTP请求为例

发布时间: 2013-02-19 11:11:41 作者: rapoo

Android实现异步处理 -- HTTP请求为例

package com.chenjun.utils;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.BlockingQueue;import java.util.concurrent.ThreadFactory;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;import java.util.concurrent.atomic.AtomicInteger;/** * 线程池辅助类,整个应用程序就只有一个线程池去管理线程。 * 可以设置核心线程数、最大线程数、额外线程空状态生存时间,阻塞队列长度来优化线程池。 * 下面的数据都是参考Android的AsynTask里的数据。 * @author zet * */public class ThreadPoolUtils {        private ThreadPoolUtils(){            }        //线程池核心线程数    private static int CORE_POOL_SIZE = 5;        //线程池最大线程数    private static int MAX_POOL_SIZE = 100;        //额外线程空状态生存时间    private static int KEEP_ALIVE_TIME = 10000;        //阻塞队列。当核心线程都被占用,且阻塞队列已满的情况下,才会开启额外线程。    private static BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(            10);        //线程工厂    private static ThreadFactory threadFactory = new ThreadFactory() {        private final AtomicInteger integer = new AtomicInteger();        @Override        public Thread newThread(Runnable r) {            return new Thread(r, "myThreadPool thread:" + integer.getAndIncrement());        }    };        //线程池    private static ThreadPoolExecutor threadPool;        static {        threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE,                MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, workQueue,                threadFactory);    }            /**     * 从线程池中抽取线程,执行指定的Runnable对象     * @param runnable     */    public static void execute(Runnable runnable){        threadPool.execute(runnable);    }}

?

? ?有了线程池之后,我们就只要编写自己的Runnable(或者是Callable)去实现业务,然后交给线程池让它分配线程并完成业务。

?

? ?这里的业务以Android的HTTP下载为例。

?

? ?对于Android的HTTP服务,我们的整个应用程序也只需要一个HttpClient对象,可以生成一个线程安全的HttpClient,这个HttpClient可以为我们多个HttpGet、HttpPost提供服务。具体代码如下,这里直接拷贝了《精通Android 3》里的源码:

?

package com.chenjun.network.http;import org.apache.http.HttpVersion;import org.apache.http.client.HttpClient;import org.apache.http.conn.ClientConnectionManager;import org.apache.http.conn.params.ConnManagerParams;import org.apache.http.conn.scheme.PlainSocketFactory;import org.apache.http.conn.scheme.Scheme;import org.apache.http.conn.scheme.SchemeRegistry;import org.apache.http.conn.ssl.SSLSocketFactory;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;import org.apache.http.params.BasicHttpParams;import org.apache.http.params.HttpConnectionParams;import org.apache.http.params.HttpParams;import org.apache.http.params.HttpProtocolParams;import org.apache.http.protocol.HTTP;/** * 辅助类,为整个应用程序提供唯一的一个HttpClient对象。 * 这个对象有一些初始化的属性连接属性,这些属性可以被HttpGet、HttpPost的属性覆盖 * @author zet * */public class HttpClientHelper {    private static HttpClient httpClient;        private HttpClientHelper(){            }        public static synchronized HttpClient getHttpClient(){        if(null == httpClient){            //初始化工作            HttpParams params = new BasicHttpParams();                        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);            HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);            HttpProtocolParams.setUseExpectContinue(params, true);                                    //设置连接管理器的超时            ConnManagerParams.setTimeout(params, 1000);                        //设置连接超时            HttpConnectionParams.setConnectionTimeout(params, 5000);            //设置Socket超时            HttpConnectionParams.setSoTimeout(params, 10000);                        SchemeRegistry schReg = new SchemeRegistry();            schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));            schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 80));                        ClientConnectionManager conManager = new ThreadSafeClientConnManager(params, schReg);                        httpClient = new DefaultHttpClient(conManager, params);        }                return httpClient;    }}

?

?

? ??

? ?这个HttpClient有一些初始化配置的属性,如果HttpGet和HttpPost没有设定特定的属性,那么生成的HttpGet和HttpPost会沿用HttpClient的初始化属性。但是我们可以根据不同的情况,为HttpGet和HttpPost设置属性,这些属性将覆盖掉HttpClient的初始化属性,这样,我们得到的HttpGet和HttpPost就有特定的属性了。

? ?

? ?具备以上的一些内容,我们就可以在自己的Activity里去实现一个Runnable和Handler即可。在Runnable里完成我们的业务逻辑,并适时的发送Message给Handler来更新UI,在Handler里处理Message并和UI交互。实例代码:

?

package com.chenjun.httpdemo;import org.apache.http.HttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.params.BasicHttpParams;import org.apache.http.params.HttpConnectionParams;import org.apache.http.params.HttpParams;import org.apache.http.util.EntityUtils;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.View;import android.widget.Toast;import com.chenjun.asynctask.DownloadImageTask;import com.chenjun.network.http.HttpClientHelper;import com.chenjun.utils.ThreadPoolUtils;public class HttpDemoActivity extends Activity {    private static final int START_DOWNLOAD_MESSAGE = 0x01;    private static final int FINISH_DOWNLOAD_MESSAGE = 0x02;    private static final int ERROR_DOWNLOAD_MESSAGE = 0x03;        private Handler myHandler;        @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);                myHandler = new MyHandler();        ThreadPoolUtils.execute(new MyRunnable());    }    private class MyRunnable implements Runnable{        @Override        public void run() {                        HttpGet httpGet = new HttpGet("http://www.sina.com.cn");                        //为这个HttpGet设置一些特定的属性,别的属性沿用HttpClient            HttpParams params = new BasicHttpParams();            HttpConnectionParams.setConnectionTimeout(params, 60000);            httpGet.setParams(params);                        myHandler.sendEmptyMessage(START_DOWNLOAD_MESSAGE);                        try {                                HttpResponse httpResponse = HttpClientHelper.getHttpClient().execute(httpGet);;                                byte[] bytes = EntityUtils.toByteArray(httpResponse.getEntity());                //在大多数情况下,这个下载下来的是XML或者Json。应该解析完组装成对象再放置到Message中。                //这里简单起见,直接变成字符串打印了                String result = new String(bytes);                                Message msg = myHandler.obtainMessage();                msg.what = FINISH_DOWNLOAD_MESSAGE;                msg.obj = result;                                myHandler.sendMessage(msg);                            } catch (Exception ex){                ex.printStackTrace();                myHandler.sendEmptyMessage(ERROR_DOWNLOAD_MESSAGE);            }        }    }        private class MyHandler extends Handler{        @Override        public void dispatchMessage(Message msg) {            switch(msg.what){            case START_DOWNLOAD_MESSAGE:                Toast.makeText(HttpDemoActivity.this, "开始下载", Toast.LENGTH_SHORT).show();                break;            case FINISH_DOWNLOAD_MESSAGE:                Toast.makeText(HttpDemoActivity.this, "下载成功", Toast.LENGTH_SHORT).show();                                //简单起见,直接输出了。                System.out.println(msg.obj);                break;            case ERROR_DOWNLOAD_MESSAGE:                Toast.makeText(HttpDemoActivity.this, "下载失败", Toast.LENGTH_SHORT).show();                break;            default:                System.out.println("nothing to do");                break;            }        }    }}

?

? 总结:个人有点不习惯用AsynTask,更倾向于这种写法。也许Google开发的AsynTask有更为深远的意义,但是我暂时还没领会到,所以就暂时沿用自己的这种写法了。

读书人网 >Android

热点推荐