افزایش عمر باتری هنگام استفاده از Retrofit 2


استفاده از cache در Retrofit 2

Retrofit 2 کتابخانه قدرتمند برای ارتباط با سرور و دریافت اطلاعات می باشد. هنگام تعامل با سرور موارد زیادی وجود دارند که باید مدیریت شوند. کتابخانه Retrofit 2 به خوبی از عهده این کار بر می آید. پیشتر در مقاله ای به آشنایی و کار با این کتابخانه پرداخته ایم. در این مقاله پیاده سازی قدم به قدم کتابخانه Retrofit در پروژه اندرویدی را بررسی نموده ایم.

هنگام تعامل با سرور مواردی باید دانلود شوند. از بین آنها مواردی وجود دارند که تکراری هستند و نباید هر بار که برنامه با سرور ارتباط می گیرد دوباره دانلود شوند. استفاده از اینترنت به تنهایی موجب نشت باتری شده و کم کم عمر آنرا کوتاه تر می کند. در نتیجه تا حد امکان باید ارتباط بهینه ای با سرور برقرار کنیم و حجم دیتای تبادلی را کاهش دهیم.

راه حل هایی برای افزایش عمر باتری هنگام ارتباط با سرور

  • Cache و فشرده سازی داده ها : جلوگیری از دانلود داده های در مواقع غیر ضروری با ذخیره سازی آنها در حافظه پنهان و استفاده در صورت لزوم. به حداقل رساندن زمان تبادل داده ها با فشرده سازی و کاهش حجم آنها.
  • مصرف کمتر باتری توسط Wifi به نسبت داده تلفن همراه: برای دانلود فایل هایی حجیم باید از wifi استفاده کرد و این محدودیت را روی دیوایس قائل شد چرا که مصرف باتری دیتای گوشی بیشتر است.
  • استفاده دوباره از object های ساخته شده برای connection به جای ساخت connection جدید
  • دانلود بیشتر با یک connection به جای استفاده از هر connection یک دانلود مجزا

طرح یک مثال برای استفاده از حافظه پنهان در استفاده از کتابخانه Retrofit 2

در این مثال از api مربوط به github استفاده می کنیم. تصویر کلی این مثال به این صورت است که درخواستی به سرور ارسال می گردد تا پاسخی دریافت شود. برای مدت زمان یک دقیقه پاسخ دریافتی در حافظه نهان یا cache باقی می ماند.

مرحله اول : افزودن کتابخانه ها به build.gradle

// rxandroid
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'

// Retrofit 2 for network tasks
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'
implementation 'com.google.code.gson:gson:2.8.2'

مرحله دوم : ساخت کلاس entity

برای نگهداری اطلاعات گرفته شده از api کلاسی متناسب با فیلدهای پاسخ سرور می سازیم :

import com.google.gson.annotations.SerializedName
data class GithubAccount(
        @SerializedName("login") var login : String = "",
        @SerializedName("id") var id : Int = 0,
        @SerializedName("avatar_url") var avatarUrl : String = "",
        @SerializedName("created_at") var createdAt : String = "",
        @SerializedName("updated_at") var updatedAt : String = "")

مرحله سوم : ساخت اینترفیس برای Retrofit

import io.reactivex.Observable
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Path

interface GithubApi {
    @GET("/users/{username}")
    fun getGithubAccountObservable(@Path("username") username: String): Observable<Response<GithubAccount>>
}

مرحله چهارم : ساخت object برای cache

سایز cache به اندازه 10mb مشخص شده است. به این معنی که cache های قدیمی، وقتی این میزان پر شود، برای نگهداری داده های جدید، از بین می روند. ()getCacheDir متدی در کلاس اکتیویتی ست که مقدار بازگشتی آن directory پیش فرض cache در اندروید است.

val cacheSize = 10 * 1024 * 1024 // 10 MB
val httpCacheDirectory = File(getCacheDir(), "http-cache")
val cache = Cache(httpCacheDirectory, cacheSize.toLong())

مرحله پنجم : ایجاد و دستیابی به cache

val networkCacheInterceptor = Interceptor { chain ->
    val response = chain.proceed(chain.request())

    var cacheControl = CacheControl.Builder()
            .maxAge(1, TimeUnit.MINUTES)
            .build()

    response.newBuilder()
            .header("Cache-Control", cacheControl.toString())
            .build()
}

مرحله ششم : ایجاد log

این مرحله ضروری نیست اما همان طور که می دانید می تواند برای زمان debug برنامه مفید باشد :

val loggingInterceptor = HttpLoggingInterceptor()
loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY

مرحله هفتم : ساخت object از HttpClient

این مرحله به منظور تنظیمات و دستیابی cache انجام می شود :

val httpClient = OkHttpClient.Builder()
        .cache(cache)
        .addNetworkInterceptor(networkCacheInterceptor)
        .addInterceptor(loggingInterceptor)
        .build()

مرحله هشتم : ساخت نمونه Retrofit با بکارگیری HttpClient

val retrofit = Retrofit.Builder()
        .baseUrl("https://api.github.com/")
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .client(httpClient)
        .build()

مرحله نهم : ایجاد درخواست به سرور و دریافت پاسخ از api

val githubApi = retrofit.create(GithubApi::class.java)
githubApi.getGithubAccountObservable("google")
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribeWith(object : DisposableObserver<Response<GithubAccount>>() {
            override fun onNext(response: Response<GithubAccount>) {

                if (response.raw().cacheResponse() != null) {
                    Log.d("Network", "response came from cache")
                }

                if (response.raw().networkResponse() != null) {
                    Log.d("Network", "response came from server")
                }

                Toast.makeText(applicationContext, response.body().toString(), Toast.LENGTH_SHORT).show()
            }

            override fun onComplete() {}

            override fun onError(e: Throwable) {
                e.printStackTrace()
            }
        })

در نهایت با پیاده سازی مرحله 4 تا 9 کلاس اکتیویتی به صورت زیر خواهد بود :

import android.content.Intent
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.view.View
import android.widget.Toast
import com.example.myapplication.data.GithubAccount
import com.example.myapplication.data.GithubApi
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.observers.DisposableObserver
import io.reactivex.schedulers.Schedulers
import okhttp3.Cache
import okhttp3.CacheControl
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.io.File
import java.util.concurrent.TimeUnit

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        loadGithubAccount()
    }


    fun loadGithubAccount() {

        // Create a cache object
        val cacheSize = 10 * 1024 * 1024 // 10 MB
        val httpCacheDirectory = File(getCacheDir(), "http-cache")
        val cache = Cache(httpCacheDirectory, cacheSize.toLong())

        // create a network cache interceptor, setting the max age to 1 minute
        val networkCacheInterceptor = Interceptor { chain ->
            val response = chain.proceed(chain.request())

            var cacheControl = CacheControl.Builder()
                    .maxAge(1, TimeUnit.MINUTES)
                    .build()

            response.newBuilder()
                    .header("Cache-Control", cacheControl.toString())
                    .build()
        }

        // Create the logging interceptor
        val loggingInterceptor = HttpLoggingInterceptor()
        loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY


        // Create the httpClient, configure it
        // with cache, network cache interceptor and logging interceptor
        val httpClient = OkHttpClient.Builder()
                .cache(cache)
                .addNetworkInterceptor(networkCacheInterceptor)
                .addInterceptor(loggingInterceptor)
                .build()

        // Create the Retrofit with the httpClient
        val retrofit = Retrofit.Builder()
                .baseUrl("https://api.github.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(httpClient)
                .build()

        // Build the gitHubApi with Retrofit and do the network request
        val githubApi = retrofit.create(GithubApi::class.java)
        githubApi.getGithubAccountObservable("google")
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeWith(object : DisposableObserver<Response<GithubAccount>>() {
                    override fun onNext(response: Response<GithubAccount>) {

                        if (response.raw().cacheResponse() != null) {
                            Log.d("Network", "response came from cache")
                        }

                        if (response.raw().networkResponse() != null) {
                            Log.d("Network", "response came from server")
                        }

                        Toast.makeText(applicationContext, response.body().toString(), Toast.LENGTH_SHORT).show()
                    }

                    override fun onComplete() {}

                    override fun onError(e: Throwable) {
                        e.printStackTrace()
                    }
                })
    }
}

 

به این پست امتیاز دهید

روی ستاره های کلیک کنید و امتیاز بدید

میانگین امتیاز 5 / 5. تعداد: 1

از امتیاز شما متشکریم

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

Enter Captcha Here : *

Reload Image