Noam Silverstein
Noam Silverstein

Reputation: 829

How to access activity context from presenter?

I had an Activity with a calculation and I extracted the functionality of that Activity in MVP pattern, for simplicity:

  1. CalcActivity
  2. CalcPresenter

Earlier I had all the calculation in one single CalcActivity. There I did some calculations in that activity:

private fun Calculator.doCalculation() {
    this.complexCalcualtion(intArrayOf(1, 2, 3, 4, 5, 6), object : CalculationCallback {
        override fun onSuccess(result: String) {
           runOnUiThread {
                result_textview.text = result
           }
        }
    })
}

This whole doCalculation() is done on another thread I guess. I moved this method to the presenter and I wanted to forward result to view:

private fun Calculator.doCalculation() {
    this.complexCalcualtion(intArrayOf(1, 2, 3, 4, 5, 6), object : CalculationCallback {
        override fun onSuccess(result: String) {
            view?.showResult(result)
        }
    })
}

But view? is never called since it is null in the CalculationCallback.onSuccess() and I cant see view there.

Also I do not have access to activity there, so I can not runOnUiThread there..

How can I forward my result back to view/activity?

Upvotes: 0

Views: 246

Answers (1)

Sergei Bubenshchikov
Sergei Bubenshchikov

Reputation: 5361

You can deliver calculation result by LiveData. This tool is integrated with activity life cycle and your data will be delivered when activity (and it views) will be in active state.

You can implement your calculator like this:

class Calculator {

    private val resultLiveData = MutableLiveData<String>().apply { value = "" }
    // expose result as live data
    val result: LiveData<String> = resultLiveData

    fun calculate(input: String) {
        // calculation in worker thread
        // ...
        // return result for live data observers
        resultLiveData.postValue("$input CALCULATED!")
    }

    fun cancel() {
        // depending on background worker
    }
}

And use it in activity (or fragment)

class MyActivity : Activity() {

    private val calculator = Calculator()

    override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
        super.onCreate(savedInstanceState, persistentState)
        calculator.result.observe(this::getLifecycle) { result ->
            // setup result in your view
            text_view.text = result
        }
    }

    override fun onStart() {
        super.onStart()
        calculator.calculate("Input data")
    }

    override fun onStop() {
        super.onStop()
        calculator.cancel()
    }
}

Upvotes: 1

Related Questions