Android Kotlin開發偶遇Rxjava、Retrofit進行網絡請求 [復制鏈接]

2019-1-2 10:44
Torr 閱讀:388 評論:0 贊:0
Tag:  

本篇能學到什么


Kotlin配合Rxjava+Retrofit+緩存策略進行網絡請求
Kotlin Retrofit簡單封裝
Kotlin使用單例模式

開始
Kotlin配合Rxjava+Retrofit+緩存策略進行網絡請求
網絡請求基本上每個應用App都要具備的需求之一,網絡請求庫也有許多,Android中用java來進行網絡請求大家恐怕都比較熟悉,那么Kotlin呢,其實也很簡單,抄家伙……Kotlin的配置這里就不在說啦,不清楚的小伙伴可以看我之前的博客:Kotlin在Android Studio中的配置 
1.首先依賴庫

    /*網絡依賴*/
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile 'com.squareup.okhttp3:okhttp:3.2.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'
    // rxjava
    compile 'io.reactivex:rxandroid:1.1.0'
    compile 'io.reactivex:rxjava:1.1.0'
    /*圖片處理*/
    compile 'com.github.bumptech.glide:glide:3.7.0'

2.Kotlin的配置略

Kotlin Retrofit簡單封裝
率性耿直的Body直接上代碼,沒什么不好理解的,跟Java封裝的差別不太大,注釋寫的也比較詳細

package com.example.kotlin.http

import com.example.kotlin.MyApplication
import com.example.kotlin.bean.Banner
import com.example.kotlin.util.NetWorkUtil
import okhttp3.*
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import rx.Observable
import java.io.File
import java.util.concurrent.TimeUnit


/**
 * 作者:Tangren on 2017/5/23 17:48
 * 郵箱:[email protected]
 * TODO:RetrofitManager
 */
class RetrofitManager private constructor(url: String) : Interceptor {

    //短緩存有效期為10分鐘
    val CACHE_STALE_SHORT = 60 * 10
    //長緩存有效期為7天
    val CACHE_STALE_LONG="60 * 60 * 24 * 7"
    //查詢緩存的Cache-Control設置,為if-only-cache時只查詢緩存而不會請求服務器,max-stale可以配合設置緩存失效時間
    val CACHE_CONTROL_CACHE = "only-if-cached, max-stale=" + CACHE_STALE_LONG
    //查詢網絡的Cache-Control設置,頭部Cache-Control設為max-age=0時則不會使用緩存而請求服務器
    val CACHE_CONTROL_NETWORK = "max-age=0"

    var mOkHttpClient: OkHttpClient? = null

    var service: APIService? = null

    //初始化
    init {
        initOkHttpclient()
        var retrofit = Retrofit.Builder()
                .baseUrl(url)
                .client(mOkHttpClient)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build()

        service = retrofit.create(APIService::class.java)

    }

    companion object {
        fun builder(url: String): RetrofitManager {
            println(RetrofitManager.javaClass.classes)
            return RetrofitManager(url)
        }
    }


    //配置緩存策略
    fun initOkHttpclient() {
        val interceptor = HttpLoggingInterceptor()
        interceptor.level = HttpLoggingInterceptor.Level.BODY
        if (mOkHttpClient == null) {
            val cache = Cache(File(MyApplication.getInstance().cacheDir, "File_Kotlin"), 14 * 1024 * 100)
            mOkHttpClient = OkHttpClient.Builder()
                    .cache(cache)
                    .retryOnConnectionFailure(true)
                    .addNetworkInterceptor(this)
                    .addInterceptor(this)
                    .connectTimeout(15, TimeUnit.SECONDS)
                    .build()
        }
    }

    //云端響應頭攔截器,用來適配緩存策略
    override fun intercept(chain: Interceptor.Chain?): Response {
        var request = chain!!.request()
        if (!NetWorkUtil.isNetWorkConnected()) {
            request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build()
        }
        var response = chain.proceed(request)
        if (NetWorkUtil.isNetWorkConnected()) {
            var cacheControl: String = request.cacheControl().toString()
            return response.newBuilder().header("Cache-Control", cacheControl)
                    .removeHeader("Pragma").build()
        } else {
            return response.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + CACHE_STALE_LONG)
                    .removeHeader("Pragma").build()
        }
    }

    fun getBanner(): Observable<List<Banner>> = service!!.getHot()

}

APIService .kt

package com.example.kotlin.http

import com.example.kotlin.bean.Banner
import retrofit2.http.GET
import retrofit2.http.Headers
import rx.Observable

/**
 * 作者:Tangren on 2017/5/23 19:12
 * 郵箱:[email protected]
 * TODO:一句話描述
 */
interface APIService {

    @Headers("Cache-Control: public, max-age=60 * 60 * 24 * 7")
    @GET("/course_api/banner/query?type=1")
    fun getHot(): Observable<List<Banner>>

}

就在這時候RxJava突然來了(轟隆轟隆……)

fun getBanner() {
        RetrofitManager.builder("http://112.124.22.238:8081")
                .getBanner()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe { println("call…………………………") }
                .subscribe({ ban ->
                    println(ban.toString())
                    adapter!!.add(ban)
                    recyclerView.adapter = adapter

                }) { throwable -> println(throwable.message) }

    }

疲倦,有時候是勞累過后,雖然只有3秒……太快了,剎那間網絡請求就可以了,就為你6不6,具體代碼請移步到:代碼在這里

Kotlin使用單例模式
java中使用單利模式有幾種方式:一種是常用但不穩妥的懶漢式、一種是惡漢式寫法但沒有lazy loading,一種是靜態內部類最后一種也是我常用的一種Double check 雙重校驗鎖寫法。具體代碼就不詳述了大家都比較清楚,Kotlin的單例模式跟java的實質是都是一樣的。

1.懶漢模式:
java代碼

public class Singleton {

    private static Singleton singleton = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return singleton;
    }
}

Kotlin代碼

object Singleton{}
1
2.懶加載(非線程安全)
java代碼

public class Singleton {

    private static Singleton instance;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

}

Kotlin代碼 
Kotlin懶加載方式有兩種: 
第一種:

class Singleton {
    companion object {
        val instance by lazy(LazyThreadSafetyMode.NONE) {
            Singleton()
        }
    }
}

第二種:

class Singleton {

    private var instance: Singleton? = null

    fun get(): Singleton {
        if (instance == null) {
            instance = Singleton()
        }
        return instance!!
    }
}

在Kotlin中如果使用懶加載推薦使用第一種,但是懶加載方式不是線程安全的,有可能還會出現不止一個實例,那么請看線程安全方式

3.懶加載(線程安全)
java代碼

public class Singleton {

    private static Singleton instance;

    private Singleton() {
    }

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

Kotlin代碼

class Singleton private constructor() {

    private var instance: Singleton? = null

    @Synchronized
    fun get(): Singleton {
        if (instance == null) {
            instance = Singleton()
        }
        return instance!!
    }
}

但是這種加鎖的方式是在每次都會,實際上只需要第一次調用才加鎖,所以性能上稍微欠缺。

4.雙重鎖
java代碼

public class Singleton {

    private static volatile Singleton instance;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if(instance==null)
                   instance = new Singleton();
            }
        }
        return instance;
    }

}

Kotlin代碼 
第一種寫法

class Singleton private constructor() {

    companion object {
        val instance by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            Singleton()
        }
    }
 }

第二種寫法:

class Singleton private constructor() {

    private @Volatile var instance: Singleton? = null

    fun get(): Singleton {
        if (instance == null) {
            synchronized(this) {
                if (instance == null) {
                    instance = Singleton()
                }
            }
        }
        return instance!!
    }
}

5.最優雅的寫法:靜態內部類
java代碼

public class Singleton {

    private static class Holder {
        private static Singleton instance = new Singleton();
    }

    private Singleton() {
    }

    public static Singleton getInstance() {
        return Holder.instance;
    }
}

Kotlin代碼

class Singleton private constructor() {

    companion object {
        fun getInstance() = Holder.instance
    }

    private object Holder {
        val instance = Singleton()
    }
}

總結
學習Kotlin是一個循環漸進的過程,最近也沒有太多的時間去研究,學習進度也相當的慢,暫時先分享這些。


我來說兩句
您需要登錄后才可以評論 登錄 | 立即注冊
facelist
所有評論(0)
領先的中文移動開發者社區
18620764416
7*24全天服務
意見反饋:[email protected]

掃一掃關注我們

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粵ICP備15117877號 )

两码中特期期