使用协程访问Koltin中Deferred <CustomObject1>内部的List <CustomObject2>

时间:2019-12-03 20:07:14

标签: android kotlin viewmodel kotlin-coroutines

我正在尝试在JSON对象中获取JSON数组并将其存储到称为store的数据类中。

我有一个self.addEventListener("install", function(event) { console.log("serviceWorker installing…"); const installCompleted=Promise.resolve().then(function() { console.log("serviceWorker installed"); }); event.waitUntil(installCompleted); }); self.addEventListener("activate", function(event) { console.log("serviceWorker activating…"); const activationCompleted=Promise.resolve().then(function() { console.log("serviceWorker activated"); }); event.waitUntil(activationCompleted); }); self.addEventListener("DOMContentLoaded", function() { //code to handle events from nodeJS (server) and notifications } ,它存储了一个data class Data引用。 List<Store>是我真正需要的。现在,通过改造和Kotlin协程,我试图获取商店数据并将其存储在Store中并访问其大小。

但是,这样做很麻烦,因为当我最后使用var storeDataasync{...}时,它给了我一个.await()类型的对象,而我无法访问Deferred

.size属性

示例JSON数据

List<Store>

StoreViewModel.kt

stores: [
{
address: "7801 Citrus Park Town Center Mall",
city: "Tampa",
name: "Macy's",
latitude: "28.068052",
zipcode: "33625",
storeLogoURL: "https://www.macys.com/img/nav/co_macysLogo3.jpeg",
phone: "813-926-7300",
longitude: "-82.573301",
storeID: "1234",
state: "FL"
},
{...

StoreApiService.kt


import android.app.Application
import android.util.Log
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.example.brandroidtest.Model.Data
import com.example.brandroidtest.Model.Store
import com.example.brandroidtest.network.StoreAPI
import kotlinx.coroutines.*
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

class StoreViewModel: ViewModel() {

    // Response from server: Either Store Data or Failure Message
    private val _response = MutableLiveData<String>()

    // Same data but will be used to display in textview in MainListActivity
    val response: LiveData<String>
        get() = _response


    private var viewModelJob = Job()
    private val coroutineScope = CoroutineScope( viewModelJob + Dispatchers.Main)

    /**
     * Call getStoreData() on init so we can display status immediately.
     */
    init {
        getStoreData()
    }

    /**
     * Sets the value of the response LiveData to the Store API data.
     */


//This is the first attempt, .await() is not accessible in this one
    private fun getStoreData() {

        coroutineScope.launch {
            var data  =  StoreAPI.retrofitService.getData()
            try {
                var storeData = data.stores.await()
                _response.value = "Success: ${storeData.size} Stores received"
            }
            catch (t: Throwable){
                _response.value = "Failure: " + t.message
                t.printStackTrace()
            }
        }
    }


//This method is the other approach that I tried. size is not accessable in this //one

//    private fun getStoreData() {
//
//        coroutineScope.launch {
//            var storeData  = async{  StoreAPI.retrofitService.getData()}.await()
//            try {
//
//                _response.value = "Success: ${storeData.size} Stores received"
//            }
//            catch (t: Throwable){
//                _response.value = "Failure: " + t.message
//                t.printStackTrace()
//
//            }
//
//        }
//
//
//    }

    override fun onCleared() {
        super.onCleared()
        viewModelJob.cancel()
    }
}

Data.kt


import com.example.brandroidtest.Model.Data
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import kotlinx.coroutines.Deferred
import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.http.GET

private const val URL = "http://sandbox.bottlerocketapps.com/BR_Android_CodingExam_2015_Server/"


private val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()

private val retrofit = Retrofit.Builder()
    .addConverterFactory(MoshiConverterFactory.create(moshi))
    .baseUrl(URL)
    .build()

interface StoreAPIService{

    //Initially was using Jake Wharton's library for retrofit2 kotlin coroutines support but it has been deprecated since the support
    // addition of the suspend keyword in retrofit 2.6.0
    //Suspend does all the task of coroutines for us by just adding it before the function declaration
    @GET("stores.json")
    suspend fun getData():
            Data //return Data object because Data has access to the Store JSON Object/Array
}

object StoreAPI{
    val retrofitService: StoreAPIService by lazy {
        retrofit.create(StoreAPIService::class.java)
    }
}

作为参考,我正在关注Udacity的Kotlin课程开发Android应用程序。

0 个答案:

没有答案