http请求是耗时操作,如果把它放到主线程上,会造成UI线程阻塞,android在API8以后不允许开发者将网络耗时操作放到主线程上进行.对于开子线程进行http请求,从服务器返回的数据,需要主线程来处理,并更新UI,子线程不能更新UI,所以这里涉及到子线程和主线程的通信.android提供handler消息处理机制来实现线程通信,子线程将网络返回结果通过发送消息的形式通知主线程,主线程接收消息,处理数据,并进行UI操作,这样就实现了整个客户端向服务器发送请求并接收请求,处理请求的过程.对于子线程设计,这里建议采取线程模板设计的方式.步骤如下

首先,自定义模板线程,继承线程类,把它设置成抽象类,作为具体线程的父类

public abstract class BaseThread extends Thread {


    protected String requestURL;

    protected Map resultMap;

    protected Map requestParams;

    protected List resultList;

    protected Handler mHandler;

    protected Message msg;

    protected String stateId;


    /**

     * handler是关于主线程的交互类

     * stateId是与主线程的message的标识号

     *

     * @param mHandler

     * @param stateId

     */

stateID用以作为message的标签

    

    public BaseThread(Handler mHandler, String stateId) {

        this.mHandler = mHandler;

        this.stateId = stateId;

    }

其次,设计一个方法,用以初始化http具体请求的url,和请求参数

 /**

     * 设置POST表单的参数和请求主机的位置

     *

     * @param requestURL

     * @param requestParams

     */

    public void setRequestPrepare(String requestURL, Map requestParams) {

        this.requestURL = requestURL;

        this.requestParams = requestParams;

    }

然后,设计一个方法,用来获取从服务器得到的字符串经过处理后的Map表,此方法为主线程服务.


 /**

     * 获取返回结果,结果为Map形式的

     *

     * @return

     */

    public Map getResultMap() {

        if (this.resultMap != null) {

            return (this.resultMap);

        } else {

            this.resultMap = new HashMap();

            return (this.resultMap);

        }


    }

设计一个方法,用以判断请求成功与否

/**

     * 根据httpUtils类返回的字符串来确定请求成功与否

     * @param str

     * @return

     */

    protected boolean dealRequestState(String str) {


        if (str != null) {

            if (str.equals("paramsException")) {

                return (false);

            } else if (str.equals("singleTonException")) {

                return (false);

            } else if (str.equals("InterNetException")) {

                return (false);

            } else if (str.equals("switchException")) {

                return (false);

            } else {

                return (true);

            }

        } else {

            Log.i("lzw","null");

            return (false);

        }

    }

随后,设计一个方法,用来存放网络状态的消息

/**

     * 通知主线程加载的状态

     *

     * @param key

     * @param state

     */

    protected void setLoadState(String key, int state) {

        this.msg = new Message();

        Bundle bd = new Bundle();

        bd.putInt(key, state);

        this.msg.setData(bd);

    }

该方法用以检查请求参数

protected void checkRequestMap()

    {

        Iterator it=this.requestParams.entrySet().iterator();

        while(it.hasNext())

        {

            Map.Entry<String,String> entry=(Map.Entry<String,String>)it.next();

           Log.i("lzw",entry.getKey());

            Log.i("lzw",entry.getValue());

        }

    }

最后,来实现run方法

/**

     * 主要的线程体方法,先是请求服务器,

     * 将服务器的返回的结果(字符)交给子类的实例化的方法来

     */

    public void run() {

        this.checkRequestMap();

    // Log.i("lzw","URL="+this.requestURL);

        try {

            //上一篇文章用到的用以实现发送http请求httputils

            //实现发送请求方法,请求参数和路径由主线程通过调用setRequestPrepare方法初始化

            //HttpUtils执行requestHttpSever方法,得到返回字符串存放在变量responseStr中

            String responseStr =

                    HttpUtils.requestHttpServer(this.requestURL, this.requestParams,

                            ComParameter.ENCODE_UTF_8, ComParameter.ENCODE_UTF_8);

            //通过调用dealRequestState函数来判断服务器连接状态,传入参数为服务器返回字符串

            if (!this.dealRequestState(responseStr)) {

                //没有返回成功,保存错误消息

                this.setLoadState(this.stateId, ComParameter.STATE_ERROR);

                //将错误消息发送给主线程,交给主线程handler处理

                this.mHandler.sendMessage(this.msg);


                return;

            }

             //若果返回的字符串正常,处理返回字符,以map的形式存放,这个方法为抽象方法,放在子类中进行

            this.dealReponseString(responseStr);

            //告诉主线程,返回成功

            this.setLoadState(this.stateId, ComParameter.STATE_RIGHT);

            this.mHandler.sendMessage(this.msg);

        } catch (Exception e) {

            this.setLoadState(this.stateId, ComParameter.STATE_ERROR);

            this.mHandler.sendMessage(this.msg);

            e.printStackTrace();

        }

    }

将处理返回字符串的方法,作为抽象方法,因为不同的请求返回的字符串可能不一样,放在子类处理

 protected abstract void dealReponseString(String responseString) throws Exception;


下面写一个子类用来继承线程模板,处理返回字符串的示例

public class FirstLoginRequestThread extends BaseThread {


    public FirstLoginRequestThread(Handler mHandler, String stateId) {

        super(mHandler, stateId);

    }


    protected void dealReponseString(String responseString) throws Exception{

        //这里的resultMap是父类属性,这个方法用来处理服务器返回字符串,向父类的Map添加内容,为主线程得到返回参数服务

        this.resultMap = new HashMap<String, String>();

        String tmpArrStr[] = responseString.split(":");

        if (tmpArrStr[1].equals("login")) {

            String tmpArrStr1[]=tmpArrStr[2].split("[+]");


            this.resultMap.put(tmpArrStr[0], tmpArrStr[1]);

            this.resultMap.put("type", tmpArrStr1[0]);

            this.resultMap.put("dataBaseId", tmpArrStr[3]);



        } else if (tmpArrStr[1].equals("unlogin")) {

            this.resultMap.put(tmpArrStr[0], tmpArrStr[1]);

            this.resultMap.put("failReason", tmpArrStr[2]);

        }


        Log.i("lzw",responseString);



       }

}