• Android中HttpURLConnection对象是怎么生成的


     1 try {
     2     URL mUrl = new URL("https://www.jianshu.com/");
     3     HttpURLConnection http = (HttpURLConnection) mUrl.openConnection();
     4     http.setRequestMethod("GET");
     5     http.setConnectTimeout(1024);
     6     http.connect();
     7     int ret = http.getResponseCode();
     8     Log.d("tag", "JianShu response:" + ret);
     9 } catch (Exception e) {
    10     e.printStackTrace();
    11 }

    上面的代码块是在Android中使用HttpURLConnection方式访问网站的最简单的代码演示。本篇文章要讲的是上述代码的前两行的流程。即如果你有一个网址字符串,Android是如何把它封装成HttpURLConnection对象的。

    其实关于HttpURLConnection访问互联网完全是属于Java层的知识,可以说与Android没有任何关系。但由于我本人是在 Android4.4 源代码环境下进行分析的,并且在Android源代码下我可以很方便地去给这些源码添加打印来跟踪其流程,因此这篇文章就叫在Android下的HttpURLConnection对象由来跟踪。

    首先来看看URL对象的实例化过程。打开源码:

    ./libcore/luni/src/main/java/java/net/URL.java

    图1 URL对象的实例化

    URL支持以旧的URL对象来实例化新URL对象,不过我想大多数情况下都是只传一个网址参数来实例化的。

    图2 URL对象的实例化

    对于只传一个网址字符串参数进来实例化的情况,上图带三个参数的URL构造方法大多数代码都不需要去理它。这里值得关心的是上图代码第180行调用的setupStreamHandler()方法。setupStreamHandler()方法里就是实例化一个URLStreamHandler对象而已。setupStreamHandler()方法前半部分也不怎么需要去关心它。只看它后半部分的实现。

    图3 setupStreamHandler()后半部分的实现

    这块代码就很通俗易懂了,就是根据你前面传进来的网址的前缀来决定实例化哪个URLStreamHandler的子类而已。本例中我们传递的是Https类型的网址,故而URL类对象中的成员变量streamHandler在实例化过后所指向的类对象是 HttpsHandler 类对象。

    ./external/okhttp/android/main/java/com/squareup/okhttp/HttpsHandler.java

    接着上图2,streamHandler变量完成赋值后就接下去执行第188行的URL解析了,这部分代码没什么好讲的。只要你传递的网址参数是合法的,就不用理会它,在我们的正常项目中,也不会有人故意传个不正确的网址下去。
    至此,URL对象的实例化就已经完成了。Android已经将我们的网址字符串转化成了URL对象了。

    --------------------------------------------------------------------------------------------------

    下面我们再看看

    mUrl.openConnection();

    这个代码在执行的时候其内部都发生了些什么。
    首先还是找到URL中关于openConnection()方法的实现。

    图4 mUrl.openConnection()

    顺着前面分析到的streamHandler的引用对象一路跟上去。发现它会调到

    ./external/okhttp/android/main/java/com/squareup/okhttp/HttpHandler.java

    图5 httphandler.openConnection()

    newOkHttpClient()方法的实现如下图所示。

    图6 newOkHttpClient()

    这里,实例化出一个OkHttpClient类对象后调用它的open()方法,将open()方法执行过后得到的对象作为URLConnection对象返回给APK调用者。

    ./external/okhttp/src/main/java/com/squareup/okhttp/OkHttpClient.java

    图7 OkHttpClient

    这块代码也够清晰明了了。就本篇例子而言,会去实例化HttpsURLConnectionImpl类对象。

    ./external/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpsURLConnectionImpl.java

    HttpsURLConnectionImpl.java继承自HttpsURLConnection.java

    ./libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java

    而HttpsURLConnection.java又继承自HttpURLConnection.java

    ./libcore/luni/src/main/java/java/net/HttpURLConnection.java

    至此,我们算是弄明白了Android在拿到用户传入的网址后都干了些什么事,并最终把它封装成HttpURLConnection对象的了。

    HttpURLConnection http = (HttpURLConnection) mUrl.openConnection();

    换言之,文首贴出的代码中的 http 变量指向的类对象其实是上面流程分析中提到的HttpsURLConnectionImpl类的对象。而假若传入的网址是 http:// 形式的,那么它指向的就是HttpURLConnectionImpl类对象了。

  • 相关阅读:
    日记10硬件与操作系统安装专用
    程序设计与算法(三)C++面向对象程序设计 (北大MOOC)
    macbook pro14 前端基本配置【20211114】
    springboot配置rabbitmq的序列化反序列化格式
    sql优化把派生表改成子查询,查询速度将变快
    Android开发 因为ViewPager与SwipeRefreshLayout冲突导致RecyclerView或者其他列表布局的item无法点击的问题
    Kotlin开发 委托
    Kotlin开发 协程的实践 Retrofit + 协程 + ViewModel
    git clean用法
    kotlin开发 高阶函数学习与记录
  • 原文地址:https://www.cnblogs.com/chorm590/p/9894959.html
Copyright © 2020-2023  润新知