今天讲下如何使用Retrofit2+RxJava2实现一个网络请求框架的步骤:
前提准备条件自然要有清单文件别忘记添加网络请求权限:
然后开始真正的代码集成实现步骤:
第一步:首先在build.gradle文件中添加以下依赖:
dependencies {
implementation 'com.squareup.okhttp3:okhttp:3.2.0'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'io.reactivex.rxjava2:rxjava:2.1.3'
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
}
第二步:在application中初始化Retrofit
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
app = this
//初始化OkHttp
okHttpInstance()
//初始化Retrofit
RetrofitInstance()
}
//初始化okhttp Retrofit
companion object {
lateinit var app: MyApp
var mOkHttpClient: OkHttpClient? = null
var mRetrofit: Retrofit? = null
fun okHttpInstance(): OkHttpClient {
var logInterceptor = HttpLoggingInterceptor((HttpLoggingInterceptor.Logger { message ->
Log.e("message", message)
}))
logInterceptor.level = HttpLoggingInterceptor.Level.BODY
mOkHttpClient = OkHttpClient().newBuilder()
.addNetworkInterceptor(logInterceptor)
.build()
return mOkHttpClient!!
}
fun RetrofitInstance(): Retrofit {
mRetrofit = Retrofit.Builder()
.baseUrl(UrlConfig.BASE_URL)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(mOkHttpClient)
.build()
return mRetrofit!!
}
}
}
第三步:建立你的配置全局网络请求Url工具类UrlConfig.kt
class UrlConfig {
companion object {
//正式服务器url
val BASE_URL = "http://mingshiapp.com"
}
}
第四步:创建你的请求主体类IPServer.kt:
/**
* @Description:配置网络请求主体业务接口
* @Author: junjiew
* @Time: 2018/7/03 14:47
*/
interface IPServer {
//网络请求测试
@GET("/test")
fun getTestData():Observable
}
第五步:在activity中调用关键代码实现:
var bean : TestData? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main)
//调用网络请求方法
initData()
}
//调用网络框架请求
private fun initDatas() {
var server = MyApp.RetrofitInstance().create(IPServer::class.java)
server.getTestData()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ result ->
bean = result as TestData
LogUtils.d(TAG,"result:"+result.toString())
}, { error ->
//Request FAIL
LogUtils.d(TAG,"error:"+error.toString())
})
}
到这里Retrofit2+RxJava2实现一个网络请求框架就已经集成完毕了,是不是很简单看起来,哈哈,兄弟,不要大意,开发最可怕的就是你把一个东西看简单了,然后真正实现的时候遇到一个坑自己半天爬不出来,这是个老搬砖的一路走过来的经验啊!哈哈
下面再补充一个用retrofit进行文件下载的实现方法:
/**
* Retrofit 网络请求接口封装
*/
interface IPServer {
// option 2: using a dynamic URL
//如果你在下载一个大的文件,Retrofit默认会将整个文件移到内存中,为了避免这种情况,我们需要为这种请求加一个特殊的注解:
// @Streaming 加入这个 @Streaming 声明后并不是将整个文件全部放入内存中,
// 而是实时的返回字节码。值得注意的是,如果你在添加了 @Streaming声明的情况下依然使用上面的方式来进行下载,Android就会抛出一个溢出
// android.os.NetworkOnMainThreadException。
//所以,最后一步就是把请求包装到一个另外的线程中,比如使用 AsyncTask
@Streaming
@GET
fun downloadFileWithDynamicUrlSync(@Url fileUrl: String): Call
}
代码调用部分:
private fun downLoadFile(url: String, fileName: String) {
var service = MyAPP.Companion.initRetrofitInstance().create(IPServer::class.java)
object : AsyncTask() {
override fun doInBackground(vararg p0: Void?): String {
var futureStudioIconFile: File? = null
var call: Call = service.downloadFileWithDynamicUrlSync(url)
call.enqueue(object : Callback {
override fun onResponse(call: Call?, response: Response?) {
if (response!!.isSuccessful) {
LogUtils.d(TAG, "server contacted and has file")
try {
//系统相册目录,这里的目录你可以根据你的需要修改,我这里下载的文件类型是图片,所以保存到了系统相册目录
futureStudioIconFile = File(Environment.getExternalStorageDirectory().toString() + File.separator + Environment.DIRECTORY_DCIM
+ File.separator + "Camera" + File.separator + fileName)
if (!(futureStudioIconFile?.parentFile?.parentFile?.exists())!!) {
LogUtils.d(TAG, "futureStudioIconFile?.parentFile 存在")
futureStudioIconFile?.parentFile?.parentFile?.mkdirs()
if (!futureStudioIconFile?.parentFile?.exists()!!) {
futureStudioIconFile?.parentFile?.mkdirs()
if (!(futureStudioIconFile?.exists())!!) {
futureStudioIconFile?.createNewFile()
} else {
LogUtils.d(TAG, "futureStudioIconFile 存在2222")
}
} else {
LogUtils.d(TAG, "futureStudioIconFile?.parentFile?.mkdir() 不成功")
}
} else {
LogUtils.d(TAG, "futureStudioIconFile?.parentFile 存在")
}
var writtenToDisk = writeResponseBodyToDisk(response.body()!!, futureStudioIconFile!!)
LogUtils.d(TAG, "file download was a success?-------> $writtenToDisk" + "文件路径是:" + futureStudioIconFile!!.absoluteFile)
if (writtenToDisk) {
//通知相册更新 ,如果没有保存到相册就不用这部操作了
var intent: Intent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
var uri: Uri = Uri.fromFile(futureStudioIconFile)
intent.data = uri
activity?.sendBroadcast(intent)
// 如果下载成功,做提示下载成功的操作
Toast.makeText(activity, "download success", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(activity, "download faile", Toast.LENGTH_SHORT).show()
}
} catch (e: Exception) {
e.printStackTrace()
}
} else {
LogUtils.d(TAG, "server contact failed")
}
}
override fun onFailure(call: Call?, t: Throwable?) {
LogUtils.d(TAG, "error")
}
})
return "sss"
}
}.execute()
}