Is it okay a presenter having Android Handler?
I know presenters should not have any Android related objects,
but I really don't have any clear answer.
Here's the thing,
this presenter runs a disk IO task on another thread,
meanwhile, the activity has to change its view.
These jobs are supposed to be done concurrently.
So I decided to pass the activity's handler as an argument
and let presenter send message to activity like this:
class FooPresenter: FooContract.Presenter {
…
private fun doDiskIOTask(handler: Handler) {
handler.sendEmptyMessage(0)
do_something_on_new_thread_and_join()
handler.sendEmptyMessage(1)
}
…
}
The activity has to know when the task is started and finished both and change view.
Could you tell me if I'm doing it any wrong or the better way?
Passing a Handler to the presenter doesn't sound like a good idea, you wouldn't be able to unit test it. I think a better approach would be to just call a method on the view and then run on UI thread from there. If your view interface is an Activity you can use the very convenient runOnUiThread method, e.g.
class MyActivity : AppCompatActivity, FooContract.View {
override fun emptyMessage0Method(){
runOnUiThread {
// manipulate views here
}
}
}
Related
how do i correctly use coroutines in a Library class which has nothing to do with the activity lifecycle?
For now, i created a private property in my class:
private val coroutineScope = CoroutineScope(Dispatchers.Main)
and have a cancel method, to cancel the scope.
public fun cancel() {
coroutineScope.coroutineContext.cancelChildren()
}
Is there any cleaner way to make this work, without having to call cancel on my library class in onPause/OnStop?
EDIT:
Also, an additional question: Does it matter, if my created CoroutineContext is in a Singleton? Like this:
public object MyObject {
private val coroutineScope = CoroutineScope(Dispatchers.Main)
}
Is there any danger of memory leaks or similar?
Simply said no, you create a scope when you need it, you cancel it when you don't need it anymore. Scope takes care of the lifecycle of all the coroutines
fired from it. A coroutine is an instance of suspendable computation. Once you do not need that computation anymore you cancel it, in order to save computational power where it's really needed. To avoid tracking all the fired coroutine by their jobs, we have a scope. Imagine having 1000 independent coroutines and having to track 1000 jobs to cancel them, instead of that, we have a scope to cancel them all at once. You can simply call scope.cancel().
One way how you can avoid manually calling cancel() in onPause/onStop is to use observation pattern, make your library class implement LifecycleObserver interface and have it observe the Lifecycle of an Activity/Fragment of interest.
A Singleton is just a single ever existing instance of a class, there's no reason why would there be any problems having CoroutineScope instance inside of it.
how do i correctly use coroutines in a Library class which has nothing to do with the activity lifecycle?
Well, I would recommend you don't create coroutineScope inside your library class, instead you turn your class function into suspend function by specifying which thread (Dispatcher) it should run on:
suspend fun doWork() {
withContext(Dispatchers.IO) { //run on IO thread
//do your stuff
}
}
AND THEN, use built-in coroutineScope like viewModelScope from ViewModel, or lifecycleScope from Activity / Fragment to execute this suspend function. Those built-in coroutineScopes will be auto-canceld after the ViewModel or Activity / Fragment get destroyed, so you don't need to worry about them:
viewModelScope.launch {
myLibrayObject.doWork() //<- suspend function, you decide the thread inside this function
}
How to choose thred (Dispatcher):
https://youtu.be/ZTDXo0-SKuU?t=392
https://developer.android.com/kotlin/coroutines/coroutines-adv#main-safety
Currently i am using MVP pattern on android with Contract.
So in example my interactor is like this:
interface MainInteractor {
interface Activity {
//function here
}
interface Presenter {
//function here
}
}
and my Presenter class contains something like this
class MainPresenter(
var activity : MainInteractor.Activity
) : MainInteractor.Presenter {
//interface function that calls API (async)
fun callNetwork() {
//code here
}
}
In sense i want to know if this kind of pattern will cause memory leak if calling network hasn't finished but the activity has already been destroyed. I know for AsyncTask, weak reference will be used to avoid memory leak. Is it the same case here? And if it does cause memory leak are there any way to fix it aside from weak reference.
You could make method attach and detach. In attach you could initialize something, in detach you could finilize something. For example you could set null to your activity contract interface variable and inside all your callbacks before call method check if not null.
Case with AsyncTask is not similar to your case. With AsyncTask we passed inside View or Activity link, it means after rotate previous activity/view destroyed, but out async task has old link and GC cannot clear memory.
For example i have a button, if user click the button, it just call finish(). Shall i tell the presenter the button is get clicked? :
//--------------HomeView.kt--------------
var presenter: HomePresenter? = null
override fun onCreate(...) {
btBack.setOnClickListener {
presenter.onBackPress()
}
}
private fun onBackPress() {
finish()
}
//--------------HomePresenter.kt--------------
var view : HomeView? = null
private fun onBackPress() {
view?.onBackPress()
}
or can i simplified it just call finish() in its onClickListener()? :
//--------------HomeView.kt--------------
override fun onCreate(...) {
btBack.setOnClickListener {
finish()
}
}
Unless you need some logic to be executed before finishing the activity, tell the presenter, otherwise I do not see much any advantage do this
As with almost all architectural questions, this comes down to personal preferences and how much you like your code to be clean.
Personally, I would suggest to always call the presenter for each interaction on the view (even if they are just one line calls).
this allows you to move all the logic out of the view and into the presenter (since all interactions on the view just pass the call directly to the presenter, without any attached logic)
it makes your whole app much more testable, since you can mock the view from the presenter and test the logic right there
it makes the architecture of your app cleaner, since you always know that calls get send to the presenter for every single interaction
it makes your code more future proof, since you can add new logic right there in the presenter call and do not have to move code around first (or worse: just be lazy and add the logic directly in the view)
Of course I have to admit that it adds quite a lot of boilerplate code, but I think this is worth it.
I am attempting to update a few UI elements in my app, after a separate class has been updated. The separate class is neither an activity nor a fragment. Could anyone point me in the right direction? Would a handler work well here, if so could you point me toward a acceptable example of handlers?
you can use this in a separe class.
public void setView(Activity activity, View view) {
activity.runOnUiThread(new Runnable() {
public void run()
{
/update your view here
}
});
}
You can get the view from your activity variable, instead of pass a view, if you prefere.
You cannot update any UI elements from a different thread than the main thread. If you are using the main thread, you can pass the View to the method in the other class and make some changes with that.
You need to link the two classes together by perhaps implementing a callback mechanism that will be processed using a handler into your main application thread, assuming that your external class can register a callback with the Activity class.
Or more simply you could use context by allowing a reference to be passed from the Activity to your other class, but you want to make sure you don't leak context.
I have typical AsyncTask that I want to properly decouple from my Activity classes and UI logic.
I think of doing it this way:
Make listener interface
public interface MyTaskListener {
void onTaskProgress(...);
void onTaskDone(...);
}
Make my Activity implement MyTaskListener and pass this reference on task creation.
Call listener methods inonPreExecute(), onProgressUpdate() and onPostExecute().
But may be I'm reinvetning the wheel and Android framework has something better already implemented? I think of something like EventBus pattern where all interested parties can register for particular event types that I can fire from my AsyncTask.
The interface is most clean way of doing this, because your task class is 'sealed', knows nothing about surrounding environment (does not access any stuff from outer class which quite tempting when you use inner classes) and communicates back with generic channel.