Android Okhttp3+Retrofit2网络加载效率优化

本文介绍了在Android开发中,由于xUtils框架存在的性能问题,如图片加载阻塞Http请求、频繁握手导致的性能损耗,以及旧版HTTP框架的过时,转向使用Okhttp3和Retrofit2进行网络加载优化。通过详细步骤展示了Okhttp3的引入、基本使用,以及与Retrofit2的结合,强调了线程调度、连接保活和取消无效请求的优化策略,以提高用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、开发背景:

我目前在做的是一个3年左右的老项目,项目开始的时候okhttp还不像现在这么火,基本上使用HttpURLConnection类来实现所有的HTTP请求,当时采用的是xUtils框架来实现异步的,回调式的接口请求。现在发现xUtils这套框架存在几个很大的问题。

老框架的性能问题:

1、xUtils的图片加载任务会阻塞Http请求,因为xUtils中的图片加载框架BitmapUtils和网络请求框架HttpUtils的线程池是共用的,这个线程池的大小默认为3,也就是说当我在下载图片的时候会阻塞Http请求数据接口的任务。这样会带来一个严重后果,当一个页面图片很多的时候,我打开一个新的页面,新的页面需要下载相应的json字符串来显示,但是由于线程池里满满的都是图片下载任务,所以用户必须等所有图片都下载完毕之后才能调json的接口,本来很快就可以显示的页面现在却要等无意义的图片的下载,大大降低了用户体验。

2、xUtils框架连接握手太频繁,根据抓包结果来看,xUtils在完成一次Http请求之后,会主动发送挥手的FIN报文,将TCP连接关闭。这样的话如果短期内频繁请求同一个服务器多次,那么每次都要重新进行三次握手的步骤,浪费了许多时间,根据抓包结果来看,大约每次连接会浪费300ms左右的时间。抓包截图如下


可以看出倒数第3行是由Android客户端主动向服务器发送FIN报文,而且发送的时间是紧接着接口数据传输完毕后的。也就是说几乎没有进行连接保活,这样如果短时间请求同一个接口多次的话,每次调用都会执行一次握手,大量的握手会消耗大量的时间,不适合目前APP会大量调用接口的情况。

3、Android 6.0发布之后,谷歌已经将所有旧版的HttpURLConnection,HttpClient,和一些和apache有关包的类和方法定义为过时方法,并且Android SDK 23之后不再内置旧版的类和接口,需要额外引用jar包,为了代码的健壮性也需要抛弃旧版Android的HTTP框架。

OkHttp3.0的引入和配置:

在我的编程经验里来看,优秀的开源框架引入起来总不会是一帆风顺的,OkHttp也是如此,这里讲讲引入过程中的几个大坑

首先在gradle里添加引用(Eclipse可以下载连个jar包直接导入项目okhttp-3.3.1.jar,okio-1.8.0.jar):

compile 'com.squareup.okhttp3:okhttp:3.2.0'
导入完打一个带签名的包马上就会出问题

注意上面这些gradle编译的报错指示note,并不影响编译进程,也不会影响打出来的apk包。这些note是progard在混淆的时候发现有重复的类报出来的,虽然不影响使用但是这里还是要分析一下,去掉重复的类。报错的矛头指向旧版的旧版的HttpURLConnection和HttpClient的类,说它们重复了,重复的包主要是org.apache.commons.codec包。

于是我在项目里搜索该包的引用,首先发现,我现在的编译版本是23,但是23已经没有这些类了,于是我添加了apache旧框架的支持jar包,在build.gradle里是这样配置的:

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"
    defaultConfig {
        applicationId "com.xxx.app"
        minSdkVersion 15
        targetSdkVersion 17
        versionCode 1
        versionName '1.0.0.0'
        multiDexEnabled true
    }
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    productFlavors {
    }
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
    packagingOptions {
        exclude 'META-INF/LICENSE.txt'
    }
    useLibrary 'org.apache.http.legacy'
    ...
}
重点是这一句useLibrary 'org.apache.http.legacy'

他会将SDK目录中\platforms\android-23\optional\org.apache.http.legacy.jar这个jar包自动添加到项目中来,而这个jar包里面就有apache的一些类。

但它又是怎样重复的呢?经过一番搜寻我又发现在xUtils这个第三方库中有一个commons-codec.jar


正是这个jar包和org.apache.http.legacy.jar中的类出现了重复,于是把xUtils第三方库中的

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值