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

发布时间 - 2026-01-10 22:11:20    点击率:

网上介绍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可以合并

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


# android和服务器通信  # android  # https通信  # android与服务器通信  # Android使用WebSocket实现多人游戏  # SpringBoot webSocket实现发送广播、点对点消息和Android接收  # Android中使用WebSocket实现群聊和消息推送功能(不使用WebView)  # android基于socket的局域网内服务器与客户端加密通信  # Android实现蓝牙客户端与服务器端通信示例  # Android编程之客户端通过socket与服务器通信的方法  # python服务器与android客户端socket通信实例  # android利用websocket协议与服务器通信  # 重复使用  # 如果你  # 出了  # 多个  # 几点  # 抛出  # 自己的  # 都是  # 都要  # 在此  # 也要  # 两种  # 更大  # 有一定  # 很高  # 这样一个  # 考虑到  # 还需要  # 新开  # 上也 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何用免费手机建站系统零基础打造专业网站?  如何在 Go 中优雅地映射具有动态字段的 JSON 对象到结构体  如何在企业微信快速生成手机电脑官网?  香港服务器部署网站为何提示未备案?  JavaScript如何实现类型判断_typeof和instanceof有什么区别  Laravel怎么做缓存_Laravel Cache系统提升应用速度的策略与技巧  网站制作大概多少钱一个,做一个平台网站大概多少钱?  html文件怎么打开证书错误_https协议的html打开提示不安全【指南】  轻松掌握MySQL函数中的last_insert_id()  高配服务器限时抢购:企业级配置与回收服务一站式优惠方案  香港服务器WordPress建站指南:SEO优化与高效部署策略  厦门模型网站设计制作公司,厦门航空飞机模型掉色怎么办?  Laravel如何处理文件下载请求?(Response示例)  网站制作公司哪里好做,成都网站制作公司哪家做得比较好,更正规?  图片制作网站免费软件,有没有免费的网站或软件可以将图片批量转为A4大小的pdf?  Laravel如何使用.env文件管理环境变量?(最佳实践)  JS实现鼠标移上去显示图片或微信二维码  Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程  专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?  Laravel如何使用Socialite实现第三方登录?(微信/GitHub示例)  Laravel Vite是做什么的_Laravel前端资源打包工具Vite配置与使用  Firefox Developer Edition开发者版本入口  如何在阿里云通过域名搭建网站?  移动端手机网站制作软件,掌上时代,移动端网站的谷歌SEO该如何做?  用v-html解决Vue.js渲染中html标签不被解析的问题  通义万相免费版怎么用_通义万相免费版使用方法详细指南【教程】  动图在线制作网站有哪些,滑动动图图集怎么做?  Laravel Facade的原理是什么_深入理解Laravel门面及其工作机制  如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?  如何在建站之星绑定自定义域名?  开心动漫网站制作软件下载,十分开心动画为何停播?  长沙企业网站制作哪家好,长沙水业集团官方网站?  Laravel请求验证怎么写_Laravel Validator自定义表单验证规则教程  公司网站制作价格怎么算,公司办个官网需要多少钱?  简单实现Android文件上传  Laravel Eloquent关联是什么_Laravel模型一对一与一对多关系精讲  如何将凡科建站内容保存为本地文件?  香港服务器网站生成指南:免费资源整合与高速稳定配置方案  Laravel如何设置自定义的日志文件名_Laravel根据日期或用户ID生成动态日志【技巧】  Edge浏览器如何截图和滚动截图_微软Edge网页捕获功能使用教程【技巧】  香港服务器网站卡顿?如何解决网络延迟与负载问题?  利用 Google AI 进行 YouTube 视频 SEO 描述优化  如何在Windows 2008云服务器安全搭建网站?  Laravel如何自定义错误页面(404, 500)?(代码示例)  Laravel如何使用Eloquent ORM进行数据库操作?(CRUD示例)  Laravel事件和监听器如何实现_Laravel Events & Listeners解耦应用的实战教程  Laravel全局作用域是什么_Laravel Eloquent Global Scopes应用指南  车管所网站制作流程,交警当场开简易程序处罚决定书,在交警网站查询不到怎么办?  Laravel怎么实现观察者模式Observer_Laravel模型事件监听与解耦开发【指南】  什么是javascript作用域_全局和局部作用域有什么区别?