При использовании Rx Java и сопрограмм получить ошибку, наблюдаемое свойство lateinit, не было инициализировано - PullRequest
1 голос
/ 14 июля 2020

Android Studio 4.0

import retrofit2.Response
import retrofit2.http.GET

interface TestRestClient {

    @GET("films")
    suspend fun getFilms(): Response<List<Film>>
}




 suspend fun getFilms(isCustomtHandle: Boolean = false): Response<*> {
            Debug.d(TAG, "getFilms: ")
            suspend fun execOperation(): Response<*> = testRestClient.getFilms()
            return runOperation(isCustomtHandle, ::execOperation)
}

В моей ViewModel

class FilmsRxJavaViewModel(application: Application) : AndroidViewModel(application) {
    companion object {
        private val TAG = FilmsRxJavaViewModel::class.java.name
    }

    lateinit var observable: Single<List<Film>>

    init {
        loadData()
    }

 
    fun loadData() {
         viewModelScope.launch(Dispatchers.Main) {
            Debug.d(TAG, "loadData: START")
            val response = TransportService.getFilms()
            val isSuccessResponse = response.isSuccessful
            if (isSuccessResponse) { // code >= 200 && code < 300;
                val filmsList : List<Film> = response.body() as List<Film>
                observable = Single.just(filmsList)
            } else { // error - status (300-599) or network failure
                val message = response.errorResponse.message
                Debug.w(TAG, "loadData: message = $message")
            }
            Debug.d(TAG, "loadData: FINISH")
        } // end coroutine
    }

}

В моей активности

class FilmsRxJavaActivity : AppCompatActivity() {
  private lateinit var filmsRxJavaViewModel: FilmsRxJavaViewModel

  override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Debug.d(TAG, "onCreate: savedInstanceState = $savedInstanceState")
        setContentView(R.layout.films_rx_java_activity)
        binding = FilmsRxJavaActivityBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)

         val dispose = filmsRxJavaViewModel.observable
         // to subscribe in IO thread
         .subscribeOn(Schedulers.newThread())
         // observe the task's result on the main thread
         .observeOn(AndroidSchedulers.mainThread())
         .subscribe({
             Debug.d(TAG, "initLogic: subscribe_filmsList(${it.size})\n$it")
         }, {
             Debug.e(TAG, "initLogic: error = $it")
         )
      }
}

Но я получаю сообщение об ошибке при открытии своей активности:

Ошибка в этой строке:

lateinit var observable: Single<List<Film>>

Подробности:

07-14 10:23:51.557 D/AndroidRuntime( 6803): Shutting down VM
--------- beginning of crash
 FATAL EXCEPTION: main
 Process: .androidtestproject.debug, PID: 6803
 java.lang.RuntimeException: Unable to start activity ComponentInfo{androidtestproject.debug/.androidtestproject.ui.activity.FilmsRxJavaActivity}: kotlin.UninitializedPropertyAccessException: lateinit property observable has not been initialized
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
 Caused by: kotlin.UninitializedPropertyAccessException: lateinit property observable has not been initialized
    at .androidtestproject.viewmodel.FilmsRxJavaViewModel.getObservable(FilmsRxJavaViewModel.kt:26)
    at .androidtestproject.ui.activity.FilmsRxJavaActivity.initLogic(FilmsRxJavaActivity.kt:54)
    at .androidtestproject.ui.activity.FilmsRxJavaActivity.init(FilmsRxJavaActivity.kt:45)
    at .androidtestproject.ui.activity.FilmsRxJavaActivity.onCreate(FilmsRxJavaActivity.kt:33)
    at android.app.Activity.performCreate(Activity.java:7802)
    at android.app.Activity.performCreate(Activity.java:7791)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
    ... 11 more

1 Ответ

1 голос
/ 14 июля 2020

Исключение происходит внутри блока else, потому что observable все еще не инициализирован

fun loadData() {
         viewModelScope.launch(Dispatchers.Main) {
            Debug.d(TAG, "loadData: START")
            val response = TransportService.getFilms()
            val isSuccessResponse = response.isSuccessful
            if (isSuccessResponse) { // code >= 200 && code < 300;
                val filmsList : List<Film> = response.body() as List<Film>
                observable = Single.just(filmsList)
            } else { // error - status (300-599) or network failure
                val message = response.errorResponse.message
                Debug.w(TAG, "loadData: message = $message")

                  // give a value to observable when error happen .
            }
            Debug.d(TAG, "loadData: FINISH")
        } // end coroutine
    }
...