android开发学习笔记——利用HttpClient和HttpPost开发同步和异步的数据交互接口

如题,android网络框架年年有新,层出不穷。对于初学者来讲,先学会一种的基本用法就够了,能实现前后端的数据交互就够了。没必要浪费太多精力。本文就以最普通的框架HttpClient+HttpPost来实现android开发中与后端Post交互,而且是同步和异步两种实现的最精简方法(尽可能一句非必要的代码都没有,做到最精简。具体有特别的要求,再自行添加相应的配置语句)。

 

一、同步方法

    要点:利用thread.join来实现同步

    优点:逻辑清晰,没有嵌套。

    缺点:只能用于数据交互,不能实现在接收到数据后动态更新UI。而且可能影响正常的UI渲染

  public String connect(final String filePath, final String...pairs){//filePath:后端文件的URL,pairs:POST传输的键值数组,偶数下标为键,奇数下标为值
            if(pairs == null || pairs.length == 0 || pairs.length%2 != 0){
                Log.e("MyError","键值对数量有误");
                return null;
            }
            final String[] result = {null};//用于记录从后端返回的字符串
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    HttpPost post = new HttpPost(filePath);
                    if(filePath == null || post == null){
                        Log.e("MyError","filePath有误");
                    }
                    else{
                        //将键值对加入pairs2
                        List pairs2 = new ArrayList<>();
                        for(int i = 0; i < pairs.length; i+=2){
                            pairs2.add(new BasicNameValuePair(pairs[i],pairs[i+1]));
                        }

                        HttpClient client = new DefaultHttpClient();
                        
                        try {
                            
                            HttpResponse response = client.execute(post);
                            if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                                //进行UTF_8解码,并且把可能由于BOM编码而导致的字符串前面有\r\n字符干扰给消除
                                result[0] = EntityUtils.toString(response.getEntity(),HTTP.UTF_8).replaceAll("\\r\\n","");
                            }
                            //返回空字符也与访问失败相同对待
                            if(result[0] != null && result[0].length() == 0){
                                result[0] = null;
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
            thread.start();
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return result[0];
    }

如果要解析JSON数据什么的,再进行一层包装就OK了。利用了thread.join()方法,使得这个方法使用起来完全可以当做同步方法来使用,不需要什么回调函数。

 

二、异步方法

但很多时候,我们需要的不是这么简单直接的同步方法,我们需要更新UI,这时只能利用Handler来更新UI,因此handler就可以当做我们的回调

 

优点:因为使用了Handler消息处理机制,可以异步更新UI。也可以利用多层Handler多层包装返回的结果

缺点:层次过多时,容易出现嵌套杂乱,逻辑不清晰,可读性差。

 

  public void connect(final String filePath, Handler handler,final String...pairs){//filePath:后端文件的URL,pairs:POST传输的键值数组,偶数下标为键,奇数下标为值
//handler:由调用出传入的handler对象,用于更新UI
            if(pairs == null || pairs.length == 0 || pairs.length%2 != 0){
                Log.e("MyError","键值对数量有误");
                return;
            }
            final String[] result = {null};//用于记录从后端返回的字符串
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    HttpPost post = new HttpPost(filePath);
                    if(filePath == null || post == null){
                        Log.e("MyError","filePath有误");
                    }
                    else{
                        //将键值对加入pairs2
                        List pairs2 = new ArrayList<>();
                        for(int i = 0; i < pairs.length; i+=2){
                            pairs2.add(new BasicNameValuePair(pairs[i],pairs[i+1]));
                        }

                        HttpClient client = new DefaultHttpClient();
                        
                        try {
                            
                            HttpResponse response = client.execute(post);
                            if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                                //进行UTF_8解码,并且把可能由于BOM编码而导致的字符串前面有\r\n字符干扰给消除
                                result[0] = EntityUtils.toString(response.getEntity(),HTTP.UTF_8).replaceAll("\\r\\n","");
                            }
                            //返回空字符也与访问失败相同对待
                            if(result[0] != null && result[0].length() == 0){
                                result[0] = null;
                            }
                            //********重点在这里***********
                            //这里创建一个消息,把从后端返回的结果放到message的obj成员中发送。
                            Message message = new Message();
                            message.obj = result[0];
                            handler.sendMessage(message);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
            thread.start();//因为这是异步的,所以不要再使用join了
      
    }

使用该方法很简单,在需要更新UI的地方调用

        

   connect(filePath, new Handler(getMainLooper()){
        @Override
        public void handleMessage(Message msg) {
            String result = msg.obj;
            //可对result进行进一步包装,比如如果是JSON字符串可以先转换为JSONArray或JSONObject
            //利用result更新你的UI
        }
    },pairs);

 

完工!同步异步按需使用,各有优劣。

你可能感兴趣的:(android开发笔记,android开发学习笔记)