OkHttp的第一课

在android客户端开发中,使用http协议向服务器交换数据时最平常的,SDK中自带的HttpURLConnection虽然能基本满足需求,但是日常使用中基本不会使用,andriod开发的思路就是坚决不造轮子,追求使用最好的轮子。所以square公司实现了一个HTTP客户端的类库——Okhttp 。

首先我们的导入相关依赖:

implementation ‘com.squareup.okhttp3:okhttp:3.3.1’

核心类

基本上就用四个类:OkHttpClient、Request、Call 和 Response。下面我们分析一下这几个类

OkHttpClient

直接new OkHttpClient()出对象,最好将其作为全局的实例进行保存,从而在App的各处都只使用这一个实例对象,这样所有的HTTP请求都可以共用Response缓存、共用线程池以及共用连接池。

public class MainApp extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
  }

  //通过内部类实现单例模式
  static class OkHttpHolder {
    private static final OkHttpClient CLIENT = new OkHttpClient();
  }

  public static OkHttpClient getClient() {
    return OkHttpHolder.CLIENT;
  }
}

需要使用的时候,直接用MainApp.getClient()调用,而且可以保证全局唯一。
接下来需要给这个client配置一些网络必要的参数如访问的代理、协议、DNS、连接超时时长。这里使用了典型的建造者模式,方便用户根据需求搭建client配置。

OkHttpClient client = new OkHttpClient.Builder()
        .dns(dns)
        .protocols(protocols)
        .proxy(proxy)
        .readTimeout(30, TimeUnit.SECONDS)
        .build();

当然在实际中我们使用默认参数就好了。

Request

Request类封装了请求报文信息:请求的Url地址、请求的方法(如GET、POST等)、各种请求头(如Content-Type、Cookie)以及可选的请求体。同样他也是使用建造者模式进行链式创建的。

Request request = new Request.Builder()
            .url("http://www.baidu.com")
            .build();

Call

Call代表了一个实际的HTTP请求,它是连接Request和Response的桥梁,通过Request对象的newCall()方法可以得到一个Call对象。Call对象既支持同步获取数据,也可以异步获取数据。对此他有两个方法:

  1. execute():同步获取,它是会阻塞线程,因此调用它一定要新开一个子线程,否则会报 android.os.NetworkOnMainThreadException,其实程序试图在其主线程上执行耗时长的任务时(如网络操作)都可能会报错。该方法返回一个Response对象。
  2. enqueue():异步获取,它不会阻塞线程,它是通过事件回调机制来实现对任务完成与否的后续操作。

Response

Response类封装了响应报文信息:状态吗(200、404等)、响应头(Content-Type、Server等)以及可选的响应体。可以通过Call对象的execute()方法获得Response对象,异步回调执行Callback对象的onResponse方法时也可以获取Response对象。

下面在一个activity中进行一个http请求:

public class MainActivity extends AppCompatActivity {
  private OkHttpClient mClient=null;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mClient = MainApp.getClient();
    //新开一个线程,使用excute()方法
    new Thread(new Runnable() {
      @Override
      public void run() {
        Request request = new Request.Builder()
            .url("http://www.baodui.com")
            .build();
        Response response = null;
        try {
          response = mClient.newCall(request).execute();
        } catch (IOException e) {
          e.printStackTrace();
        }

        if (!response.isSuccessful())
          return;
        try {
          System.out.println(response.body().string());
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }).start();
  }


  //通过异步方法enqueue()
  private void run(){
    Request request = new Request.Builder()
        .url("http://www.baidu.com")
        .build();
    mClient.newCall(request).enqueue(new Callback() {
      @Override
      public void onFailure(Call call, IOException e) {
        e.printStackTrace();
      }
      @Override
      public void onResponse(Call call, Response response) throws IOException {
        if (!response.isSuccessful()) 
          return;
        System.out.println(response.body().string());
      }
    });
  }
}

注意

这里有几点需要注意:

  1. 在AndroidManifest.xml中需要在<application>中添加android:name=".MainApp"
  2. 在AndroidManifest.xml中打开网络权限<uses-permission android:name="android.permission.INTERNET"/>
  3. android9之后限制使用http协议直接进行网络请求,我的解决方法是在res下新建一个xml文件夹,然后添加一个叫做netconfig.xml文件,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true" />
</network-security-config>

最后在AndroidManifest.xml中的<application>中添加android:networkSecurityConfig="@xml/netconfig"即可

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值