2

In my current Android project I have a dialog that retrieves a list of objects from a webservice and show these in a list. It has a problem though. The webservice (outside my control) is not the fastest, so the process takes a while and often the user changes the orientation of the device while this process is ongoing. For now the orientation change results in the original webservice call to be cancelled and a new one is created, but this is not how it should be done I know. I would like the dialog to able to continue the loading from the webservice when an orientation change happens, but I just can't get my head around how to do this. How is it possible to hook into an ongoing call and display this state in the view (the dialog)? Any recommendations are appreciated. I've played around with Android Architecture Components and kotlins sealed classes saving the viewstate in a livedata object that the view observes, but have not found a solution that I like.

I believe a lot of developers use RxJava for this kind of issue. Is this my only option?

Btw. at the moment I use MVP architecture in my project.

Edit

This is where I cancel the job - if the listener is null its cancelled (I'm using kotlin coroutines):

override fun getWorklist() {
    job = onWorkerThread {
        val result = repository.getResult().awaitResult()
        onMainThread {
            when (result) {
                is Result.Ok -> listener?.onResult(result.getOrDefault(emptyList())) :? job.cancel()
                // Any HTTP error
                is Result.Error -> listener?.onHttpError(result.exception) :? job.cancel()
                // Exception while request invocation
                is Result.Exception -> listener?.onException(result.exception) :? job.cancel()
            }
        }
    }
}

Edit 2

I've tried controlling the viewstate using this Android Arch ViewModel, but the MediatorLiveData object isn't triggered on changes of the viewstate object. And the view stays in Loading state:

class MainModel : ViewModel() {

    private var job: Job? = null

    val viewState = MutableLiveData<MainViewState>().apply { value = Loading("Warsaw") }

    val dataGetter = MediatorLiveData<MainViewState>().apply {
        addSource(viewState, {
            Log.d("MainModel", "Viewstate is: " + viewState.value.toString() + ")...")
            when(it) {
                is Loading -> {
                    Log.d("MainModel", "Launching coroutine...")
                    job = launch(UI) {
                        Log.d("MainModel", "Loading...")
                        val items = Repository.getWorklist()
                        Log.d("MainModel", "Charts retrieved...")
                        this@MainModel.viewState.postValue(Success(it.items))
                        Log.d("MainModel", "Posted update to viewstate...")
                    }
                }
            }
        })
    }

    override fun onCleared() {
        Log.d("MainModel", "Clearing ViewModel")
        job?.cancel()
    }
}

interface ViewState

sealed class MainViewState : ViewState
class Loading() : MainViewState()
class Error(val error: String) : MainViewState()
class Success(val items: List<WorklistItem>) : MainViewState()
Bohsen
  • 4,242
  • 4
  • 32
  • 58
  • you can achieve by [this](https://stackoverflow.com/questions/12457352/fix-orientation-of-screen-on-dialog-view) – Hemant Parmar Jan 30 '18 at 07:56
  • You should show where and when you are cancelling your call and re-sending it. – Abbas Jan 30 '18 at 07:56
  • BTW if you are cancelling the call in `onDestroy()` as is most common. You can add the following lines to your mainfiest file under activity `android:configChanges="orientation|screenSize"`. Normally on orientation change activity is destroyed and recreated, this basically says that you will handle the layout changes on your own. – Abbas Jan 30 '18 at 07:58
  • 1
    saving the state of dialog is not the problem. But keeping the service is. you can save the sate of dialog but on orientation change asyncTask will be called again or it will point to wrong activity. Take a look at this answer here it will help you: https://stackoverflow.com/questions/7128670/best-practice-asynctask-during-orientation-change – Umair Jan 30 '18 at 08:04
  • @Abbas I've edited the post – Bohsen Jan 30 '18 at 08:07
  • At the moment the webservice call is continued on a configuration change using a Android Arch ViewModel and then the presenter adds a listener to the viewmodel. But I keep running into situations where the listener is null in the time that the presenter is being recreated on orientation changes. – Bohsen Jan 30 '18 at 08:15
  • Well. If the Presenter was kept alive in the ViewModel, this wouldn't be a problem – EpicPandaForce Jan 30 '18 at 09:49

0 Answers0