欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android使用http协议与服务器通信的实例

程序员文章站 2024-02-22 17:15:23
网上介绍android上http通信的文章很多,不过大部分只给出了实现代码的片段,一些注意事项和如何设计一个合理的类用来处理所有的http请求以及返回结果,一般都不会提及。...

网上介绍android上http通信的文章很多,不过大部分只给出了实现代码的片段,一些注意事项和如何设计一个合理的类用来处理所有的http请求以及返回结果,一般都不会提及。因此,自己对此做了些总结,给出了我的一个解决方案。

首先,需要明确一下http通信流程,android目前提供两种http通信方式,httpurlconnection和httpclient,httpurlconnection多用于发送或接收流式数据,因此比较适合上传/下载文件,httpclient相对来讲更大更全能,但是速度相对也要慢一点。在此只介绍httpclient的通信流程:

1.创建httpclient对象,改对象可以用来多次发送不同的http请求

2.创建httppost或httpget对象,设置参数,每发送一次http请求,都需要这样一个对象

3.利用httpclient的execute方法发送请求并等待结果,该方法会一直阻塞当前线程,直到返回结果或抛出异常。

4.针对结果和异常做相应处理 

根据上述流程,发现在设计类的时候,有几点需要考虑到:

1.httpclient对象可以重复使用,因此可以作为类的静态变量

2.httppost/httpget对象一般无法重复使用(如果你每次请求的参数都差不多,也可以重复使用),因此可以创建一个方法用来初始化,同时设置一些需要上传到服务器的资源

3.目前android不再支持在ui线程中发起http请求,实际上也不该这么做,因为这样会阻塞ui线程。因此还需要一个子线程,用来发起http请求,即执行execute方法

4.不同的请求对应不同的返回结果,对于如何处理返回结果(一般来说都是解析json&更新ui),需要有一定的*度。

5.最简单的方法是,每次需要发送http请求时,开一个子线程用于发送请求,子线程中接收到结果或抛出异常时,根据情况给ui线程发送message,最后在ui线程的handler的handlemessage方法中做结果解析和ui更新。这么写虽然简单,但是ui线程和http请求的耦合度很高,而且代码比较散乱、丑陋。

基于上述几点原因,我设计了一个postrequest类,用于满足我的http通信需求。我只用到了post请求,如果你需要get请求,也可以改写成getrequest

package com.handspeaker.network;

import java.io.ioexception;
import java.io.unsupportedencodingexception;
import java.net.uri;
import java.net.urisyntaxexception;
import java.util.concurrent.executorservice;
import java.util.concurrent.executors;

import org.apache.http.httpresponse;
import org.apache.http.client.clientprotocolexception;
import org.apache.http.client.httpclient;
import org.apache.http.client.methods.httppost;
import org.apache.http.entity.stringentity;
import org.apache.http.impl.client.defaulthttpclient;
import org.apache.http.params.httpconnectionparams;
import org.apache.http.params.httpparams;
import org.apache.http.protocol.http;
import org.apache.http.util.entityutils;
import org.json.jsonobject;

import android.app.activity;
import android.content.context;
import android.net.connectivitymanager;
import android.os.handler;
import android.util.log;

/**
 * 
 * 用于封装&简化http通信
 * 
 */
public class postrequest implements runnable {
  
  private static final int no_server_error=1000;
  //服务器地址
  public static final string url = "fill your own url";
  //一些请求类型
  public final static string add = "/add";
  public final static string update = "/update";
  public final static string ping = "/ping";
  //一些参数
  private static int connectiontimeout = 60000;
  private static int sockettimeout = 60000;
  //类静态变量
  private static httpclient httpclient=new defaulthttpclient();
  private static executorservice executorservice=executors.newcachedthreadpool();
  private static handler handler = new handler();
  //变量
  private string strresult;
  private httppost httppost;
  private httpresponse httpresponse;
  private onreceivedatalistener onreceivedatalistener;
  private int statuscode;

  /**
   * 构造函数,初始化一些可以重复使用的变量
   */
  public postrequest() {
    strresult = null;
    httpresponse = null;
    httppost = new httppost();
  }
  
  /**
   * 注册接收数据监听器
   * @param listener
   */
  public void setonreceivedatalistener(onreceivedatalistener listener) {
    onreceivedatalistener = listener;
  }

  /**
   * 根据不同的请求类型来初始化httppost
   * 
   * @param requesttype
   *      请求类型
   * @param namevaluepairs
   *      需要传递的参数
   */
  public void inirequest(string requesttype, jsonobject jsonobject) {
    httppost.addheader("content-type", "text/json");
    httppost.addheader("charset", "utf-8");

    httppost.addheader("cache-control", "no-cache");
    httpparams httpparameters = httppost.getparams();
    httpconnectionparams.setconnectiontimeout(httpparameters,
        connectiontimeout);
    httpconnectionparams.setsotimeout(httpparameters, sockettimeout);
    httppost.setparams(httpparameters);
    try {
      httppost.seturi(new uri(url + requesttype));
      httppost.setentity(new stringentity(jsonobject.tostring(),
          http.utf_8));
    } catch (urisyntaxexception e1) {
      e1.printstacktrace();
    } catch (unsupportedencodingexception e) {
      e.printstacktrace();
    }
  }

  /**
   * 新开一个线程发送http请求
   */
  public void execute() {
    executorservice.execute(this);
  }

  /**
   * 检测网络状况
   * 
   * @return true is available else false
   */
  public static boolean checknetstate(activity activity) {
    connectivitymanager connmanager = (connectivitymanager) activity
        .getsystemservice(context.connectivity_service);
    if (connmanager.getactivenetworkinfo() != null) {
      return connmanager.getactivenetworkinfo().isavailable();
    }
    return false;
  }

  /**
   * 发送http请求的具体执行代码
   */
  @override
  public void run() {
    httpresponse = null;
    try {
      httpresponse = httpclient.execute(httppost);
      strresult = entityutils.tostring(httpresponse.getentity());
    } catch (clientprotocolexception e1) {
      strresult = null;
      e1.printstacktrace();
    } catch (ioexception e1) {
      strresult = null;
      e1.printstacktrace();
    } finally {
      if (httpresponse != null) {
        statuscode = httpresponse.getstatusline().getstatuscode();
      }
      else
      {
        statuscode=no_server_error;
      }
      if(onreceivedatalistener!=null)
      {
        //将注册的监听器的onreceivedata方法加入到消息队列中去执行
        handler.post(new runnable() {
          @override
          public void run() {
            onreceivedatalistener.onreceivedata(strresult, statuscode);
          }
        });
      }
    }
  }

  /**
   * 用于接收并处理http请求结果的监听器
   *
   */
  public interface onreceivedatalistener {
    /**
     * the callback function for receiving the result data
     * from post request, and further processing will be done here
     * @param strresult the result in string style.
     * @param statuscode the status of the post
     */
    public abstract void onreceivedata(string strresult,int statuscode);
  }

}

代码使用了观察者模式,任何需要接收http请求结果的类,都要实现onreceivedatalistener接口的抽象方法,同时postrequest实例调用setonreceivedatalistener方法,注册该监听器。完整调用步骤如下:

1.创建postrequest对象,实现onreceivedata接口,编写自己的onreceivedata方法

2.注册监听器

3.调用postrequest的inirequest方法,初始化本次request

4.调用postrequest的execute方法

 可能的改进:

1.如果需要多个观察者,可以把只能注册单个监听器改为可以注册多个监听器,维护一个监听器list。

2.如果需求比较简单,并希望调用流程更简洁,inirequest和execute可以合并

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。