रेट्रोफिट और कोरटाइन्स का उपयोग करते हुए कोटलिन पर Android LiveData

यह आलेख Android घटक ViewModel, LifeCycle और LiveData का उपयोग करने के बारे में बात करता है। ये घटक आपको गतिविधि जीवन चक्र की परवाह नहीं करने की अनुमति देते हैं।

रेट्रोफिट रिपॉजिटरी के साथ संयोजन में आधुनिक कोराउटीन के उपयोग का एक उदाहरण भी माना जाता है।

fun main(args: Array<String>): Unit = runBlocking { // Wait (suspend) for Result val result: Result<User> = api.getUser("username").awaitResult() // Check result type when (result) { //Successful HTTP result is Result.Ok -> saveToDb(result.value) // Any HTTP error is Result.Error -> log("HTTP error with code ${result.error.code()}", result.error) // Exception while request invocation is Result.Exception -> log("Something broken", e) } } 

रिट्रोफिट कोरटाइन्स एक्सटेंशन

kotlin-coroutines-पुराना वापस
कोटलिन पर रेट्रोफिट के लिए एक्सटेंशन। ये सिर्फ दो फाइलें हैं। मैंने उन्हें प्रोजेक्ट में शामिल किया। आप ग्रैडल में डिपेंडेंसी के जरिए उन्हें कनेक्ट कर सकते हैं। गिथुब पर उपयोग के उदाहरण हैं।
हम एडॉप्टर addCallAdapterFactory (CoroutineCallAdapterFactory ()) भी कनेक्ट करते हैं।
ServerAPI और रिपोजिटरी एक ही फाइल में हैं

अन्य एपीआई

Kotlin पर REST API कार्यान्वयन। उसके पास कोई विशिष्ट परिवर्तन नहीं है।

ServerAPI
 import android.arch.lifecycle.MutableLiveData import android.util.Log import com.jakewharton.retrofit2.adapter.kotlin.coroutines.experimental.CoroutineCallAdapterFactory import kotlinx.coroutines.experimental.android.UI import kotlinx.coroutines.experimental.async import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Call import retrofit2.http.* import ru.gildor.coroutines.retrofit.Result import ru.gildor.coroutines.retrofit.awaitResult object ServerAPI { var API_BASE_URL: String = getNetworkHost(); var httpClient = OkHttpClient.Builder().addInterceptor( HttpLoggingInterceptor().apply { level = if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE }) var builder: Retrofit.Builder = Retrofit.Builder() .baseUrl(API_BASE_URL) .addCallAdapterFactory(CoroutineCallAdapterFactory()) .addConverterFactory(GsonConverterFactory.create()) var retrofit = builder .client(httpClient.build()) .build() var netService = retrofit.create<NetService>( NetService::class.java!!) interface NetService { @GET("api/stores") fun getStoreAll(@Header("Authorization") bearer: String): Call<Array<Store>> } } 


LiveData

अगला, रिपॉजिटरी पर विचार करें। यह LiveData प्राप्त करने के लिए मुख्य सेवा है। हम लोड स्थिति के साथ LiveData को आरंभीकृत करते हैं: Resource.loading (नल) । इसके बाद, अनुरोध के अंत की प्रतीक्षा करें प्रतीक्षा की जा रही है () इस कॉल को Coroutin async (UI) ब्लॉक में होना चाहिए

अनुरोध के अंत में, हम परिणाम को संभाल सकते हैं। यदि सब कुछ ठीक है, तो परिणाम को mutableLiveData.value = Resource.success (result.value) में संग्रहीत किया जाएगा महत्वपूर्ण बिंदु यह है कि नए उदाहरण के लिए एक लिंक होना चाहिए, अन्यथा पर्यवेक्षक LiveData काम नहीं करेगा। देखें: नया संसाधन <> (सफलता, डेटा, अशक्त);

कोष
  class Repository { fun getStores(token: String) : MutableLiveData<Resource<Array<Store>>>{ val mutableLiveData = MutableLiveData<Resource<Array<Store>>>() mutableLiveData.value = Resource.loading(null) val req = PostsAPI.netService.getStoreAll(token) try { async(UI) { val result = req.awaitResult() // Check result type when (result) { //Successful HTTP result is Result.Ok -> { mutableLiveData.value = Resource.success(result.value) } // Any HTTP error is Result.Error -> { mutableLiveData.value = Resource.error("Http Error!", null) } // Exception while request invocation is Result.Exception -> Log.d(TAG, result.exception.message) } } } catch (e: Exception) { Log.d(TAG, e.toString()) } return mutableLiveData } } 


आवरण डेटा

फ्रैगमेंट में त्रुटि को संभालने और राज्य हस्तांतरण के लिए, आवरण - संसाधन <T> का उपयोग किया जाता है

यह तीन राज्यों को संग्रहीत करता है:

 public enum Status { SUCCESS, ERROR, LOADING } 

डेटा ही:

 @Nullable public final T data; 

संसाधन <टी>
एक सामान्य वर्ग जिसमें इस डेटा को लोड करने के बारे में डेटा और स्थिति है

 // A generic class that contains data and status about loading this data. public class Resource<T> { @NonNull public final Status status; @Nullable public final T data; @Nullable public final String message; private Resource(@NonNull Status status, @Nullable T data, @Nullable String message) { this.status = status; this.data = data; this.message = message; } public static <T> Resource<T> success(@NonNull T data) { return new Resource<>(Status.SUCCESS, data, null); } public static <T> Resource<T> error(String msg, @Nullable T data) { return new Resource<>(Status.ERROR, data, msg); } public static <T> Resource<T> loading(@Nullable T data) { return new Resource<>(Status.LOADING, data, null); } public enum Status { SUCCESS, ERROR, LOADING } } 


ViewModel

StoreViewModel भंडार से डेटा का अनुरोध करता है और इसे स्टोर चर में संग्रहीत करता है

 val api = Repository() stores = api.getStores(token) 

ViewModel
 class StoresViewModel (context: Context, token: String) : ViewModel() { val stores: MutableLiveData<Resource<Array<Store>>> init { val api = Repository() stores = api.getStores(token) } } 


ViewModelProviders

ViewModel के मापदंडों को पास करने के लिए, हम मानक ViewModelProviders का विस्तार करते हैं
उदाहरण के लिए, LoginViewModel को पास करने के लिए आपको दो मापदंडों (लॉगिन, पासवर्ड) की आवश्यकता होती है। टोकन को स्टोर व्यूमॉडल में स्थानांतरित करने के लिए, एक (टोकन) का उपयोग किया जाता है

AppViewModelFactory
 class AppViewModelFactory(private val contect: Context, vararg params: Any) : ViewModelProvider.NewInstanceFactory() { private val mParams: Array<out Any> init { mParams = params } override fun <T : ViewModel> create(modelClass: Class<T>): T { return if (modelClass == LoginViewModel::class.java) { LoginViewModel(contect, mParams[0] as String, mParams[1] as String) as T } else if (modelClass == StoresViewModel::class.java) { StoresViewModel(contect, mParams[0] as String) as T } else { super.create(modelClass) } } } 


टुकड़ा

StoreViewModel प्राप्त करना:

 viewModel = ViewModelProviders.of(this, AppViewModelFactory(requireActivity(), tokenHolder.token)).get(StoresViewModel::class.java) 

डेटा परिवर्तन के लिए प्रेक्षक का उपयोग करना:

  // Observe data on the ViewModel, exposed as a LiveData viewModel.stores.observe(this, Observer<Resource<Array<Store>>> { storesResource -> 

टुकड़ा
  override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view = inflater.inflate(R.layout.stores_fragment, container, false) val tokenHolder = TokenHolder(PreferenceManager.getDefaultSharedPreferences(requireActivity())) viewModel = ViewModelProviders.of(this, AppViewModelFactory(requireActivity(), tokenHolder.token)).get(StoresViewModel::class.java) recyclerView = view.findViewById<RecyclerView>(R.id.store_list).apply { setHasFixedSize(true) } return view } override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) // Observe data on the ViewModel, exposed as a LiveData viewModel.stores.observe(this, Observer<Resource<Array<Store>>> { storesResource -> val stores = storesResource?.data stores?.let { viewAdapter = StoresAdapter(stores!!) recyclerView.adapter = viewAdapter } if (storesResource?.status == Resource.LOADING){ log("Loading...") } if (storesResource?.status == Resource.ERROR){ log("Error : " + storesResource?.message) } }) } 


पुनश्च

टोकन को संग्रहीत करने और इसे पूरे आवेदन में उपयोग करने के लिए, मैंने फैबियो कोलिनी से पुस्तकालय / विस्तार का उपयोग किया। आवेदन उनके लेख में अच्छी तरह से वर्णित है। लिंक इस आलेख में Github पर या नीचे एक पृष्ठ पर है।

Fabio Collini द्वारा प्रीफ़ेट्स-प्रतिनिधि

 class TokenHolder(prefs: SharedPreferences) { var token by prefs.string() private set var count by prefs.int() private set fun saveToken(newToken: String) { token = newToken count++ } } 

Gradle

  implementation 'android.arch.lifecycle:extensions:1.1.1' implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.30.0" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:0.30.0" implementation "com.squareup.retrofit2:retrofit:2.4.0" implementation "com.squareup.retrofit2:converter-gson:2.4.0" implementation "com.jakewharton.retrofit:retrofit2-kotlin-coroutines-experimental-adapter:1.0.0" // If you use Kotlin 1.2 or 1.3 // compile 'ru.gildor.coroutines:kotlin-coroutines-retrofit:0.13.0' // compile 'ru.gildor.coroutines:kotlin-coroutines-retrofit:0.13.0-eap13' 

लिंक

सभी एक उदाहरण में।

Android आर्किटेक्चर घटक नमूने

LiveData अवलोकन

कोडिन कॉरटाइन्स का उपयोग कर Async कोड

मल्टीथ्रेडिंग और कोटलिन

Source: https://habr.com/ru/post/hi427475/


All Articles