Android MVP: Handling all exceptions inside a presenter class - android

I'm implementing an android application in MVP architecture.
I keep a reference to view inside my presenter and do time-consuming tasks such as loading from network inside my model.
My problem is that in each call inside my presenter which I want to call a method of View, it may happen that view is destroyed already and its reference is set to null inside presenter.
So when I received results from model, before each call like mView.updateUISomehow() in need to add if (mView!=null) since when control reaches to this point it may happen that mView is null.
I want to know are there any methods that I skip all null checking and handle all possible exception of presenter class in a class-wide exception handler.
P.S. I know about MVVM, LiveData and Room. I want to resolve this exact problem :)

BasePresenter<View>{
View view
updateUI(){
if(view != null)
callUI()
}
abstract callUI();
}
Your controller would have the knowledge of updateUI(), you may choose how to handle that
YourPresenter<ThatElusiveview> extends BasePresenter<ThatElusiveEview>{
callUI(){
// hoping this is not directly called from the controller!!
}
}
I faced the same problem when I was using MVP with too many UI update calls which will happen in the real scenarios. Well did the refactor to Jet pack. I understand your dilemma.
I believe it is doable if you provide Presenter with listener to view, so if view gets destroyed, Presenter will hold the communication from the controller toward View.
it does sound like checking the view != null, but you can have enumerations of different type of updates going from presenter to View. which you can put in one place to check and then direct them to respective update method depending on the type of enumeration action.
This will also help reading the code regarding different action that presenter is capable of sending to the View

Related

Android Architecture Components, android binding and LiveData

I was wondering whether android binding is compatible with live data on conceptual level.
There is a simple task: call server after button is clicked.
So in my view I have
android:onClick="#{viewmodel::onOrderButtonClick}"
and proper onOrderButtonClick(View) method is defined in ViewModel.
But in order to make server call via LiveData I need my Fragment reference (observe() method needs LifecycleOwner instance as first parameter).
Of course I cannot hold reference to fragment in my ViewModel.
What is the pattern here? Do I really need to implement all event methods in the fragment class and delegate them back into view model class?
After some digging there is a bad news and a good one.
The bad news is that the fragment has to be used anyway (there is always some code in the fragment for each livedata event)
The good one is that it can be done relatively clean:
Call getOrderObservable() from fragment to view model. It returns
MutableLiveData<> created in view model's ctor.
Then call observe() on that observable In view model's onOrderButtonClick()
In onOrderButtonClick() in view model just call setValue()
That solution in my opinion minimalizes amount of code in the fragment. Still it looks not so elegant to separate making the network call and handling the result

Android MVP - Calling View method inside View implementation (Fragements or Activity)

I was implementing MVP in my new application, then I came across a problem. I needed to call a method of View, inside View (Activity) itself. It is by definition of MVP code separation, wrong thing to do.
By definition:
The Presenter is in charge of the the orchestration between the Model and the View. It basically receive events from both and act consequently. The Presenter is the only component that knows others. It has a reference to the View and a another to the Model. (source)
In the same article it was mentioned that View does not reacts to user interactions, it passes control to Presenter to do the job. I have also read this SOF post about dependency rules.
In my case, I am using custom AppTheme. AppTheme needs to be set before setContent() call, what I am doing is create a method in View interface called setAppTheme() which my Activity implements, and there is code to apply theme. Now the problem is, this is called within the app, which makes calling of a View method inside its implementation.
To sum up, what my understanding of MVP either one of the following
should be true:
Do call View method inside Activity, because setTheme() wont work after setContent() and our presenter.setView() is in
onResume(), but will this satisfy MVP separation of M-V-P ?
Do not make interface method for setAppTheme(), instead create a private method in Activity which sets theme. This method will have
nothing to do with any layer of MVP. But question is, if project is
using MVP pattern, is this practice valid?
Here is my MVP:
public class AboutUsMVP
{
public interface Model
{
String getFbLink();
String getTwitterLink();
String getEmailLink();
String getCompanyLink();
}
public interface Presenter
{
void setView( View view );
void fbButtonClicked();
void twitterButtonClicked();
void emailButtonClicked();
void imageButtonClicked();
}
public interface View
{
void showFacebookPage();
void showTwitterPage();
void showEmailIntent();
void showCompanyWebsite();
void setAppTheme();
void setCustomActionBar();
}
}
Please do point out mistakes where I missed them.
From what I know, same case can be argued in the light of
setActionBar() and setOnClickListener() methods, although these
may require their separate post, but they are more relevant here and
new post for either of them will be duplicate.
Please note that my Activity implements View interface.
EDIT: More explanation
My View is actually Activity class. This is View of MVP, not Android API's View class. The thing is, there is a method setAppTheme() which only related to View of MVP, (Activity of Android). This call is not in the Contract (AboutUsMVP.java) which by Google convention should be AboutUsContract.java, this setAppTheme() is not in Contract, and it cant be, so does this violate MVP principle?
There is no possible alternative, one can say make an interface of setAppTheme(), if I do so, it will not work because:
setAppTheme() is called just after super() method, if not it is useless. And MVP's presenter starts working in onResume. If an interface is made, and setAppTheme() is brought into MVP's jurisdiction, it will have no effect.
Indeed, Views in an MVP are supposed to be dumb. This is: they don't contain any logic. Just receive the event generated by the user and immediately delegate its work to the presenter. The View can also inform the presenter that some events have happened (the view has been created, the screen rotate, etc)
This can lead to some confusions. Who is responsible of calling some methods? As you said the View has to perform some actions like setOnClickListener but the presenter is responsible of handling the event. Just have this in mind:
The View is just an interface. This means that you can use anything that implements that interface
Right now you're making a mobile app. But if you wanted to code a console or a desktop app, the presentation logic doesn't change. Anything that is specific to the "View technology" (android, desktop, etc) should be performed inside the code specific to that technology. This way your code will be loosely coupled to your tech stack
I believe #Pelocho answer is correct and you should mark it as the right one. But I would like to present my answer (that agrees with his) but from an alternative point-of-view. On for this different POV I would like to debate your on definition of presenter:
The Presenter is in charge of the the orchestration between the Model
and the View
So the question I propose here is: "what is this model that the presenter interacts with?". And my answer to it is to look into the classic "note-taking" application and argue that the model is text and associated meta-data, usually stored in some DB that the presenter will read, parse and push to the view.
Nowhere in this "model" the application theme is relevant. Theme is purely a function of the view. Theme is only associated to the final on-screen looks of it. Just like the view is the one in charge of layouting the content on screen, or to know what font size to use.
And that means even if those layouting, size, colors can be changed from a user settings option, it still falls outside the responsibility of the presenter and the model, as they're only interested in the content.
tl;dr:
Just read the theme on the Activity.onCreate (before super.onCreate) directly from the SharedPreferences and do not involve the Presenter on it.

MVP and Android Handling Lifecycle events, where to do UI logic

I am converting my application to use the MVP pattern. There is some debate between the developers on the proper use of MVP especially in regards to the Android lifecycle and where the UI related logic goes. There is no debate that any hard logic should be done in the presenter, and that the network
In the case I need to do Anything for lifecycle functions, onresume, onPause, etc. Should I ...
Call a mPresenter.onResumeEvent(); The presenter then does calls. IE
contract.restoreState(); contract.connectToService() etc.
or
Do all the logic I need here and not involve the controller. IE
restoreState, start up loading spinners, etc.
I view it as onResume is an event. All events should be processed by the Presenter. The counter arguments is, we do not want to write code that "ping pongs," I.E. OnResume -> Presenter -> one line function that shows a spinner (or something close to that effect)
Now a bit more granule.
Lets says I start my activity, and I need to show either an error or the data depending if the data is null.
I could either do..
(presenter)
contract.setupUi(data);
then
(view)
setupUi(Object data){
if(data != null){
//show data
}
else{
//show error
}
Which has the UI controlling the state evoked from the presenter.
Or I could do
(presenter)
if(data != null){
contract.showUI(data);
}
else{
contract.showError();
}
Which has the contract looking at all the states.
Is the over all goal to have the Presenter Completely control everything about the application and treat the view as completely Dumb. Or is it just dividing up the code purely for testing purposes. Or is it both?
Recap.
How should I handle the lifecycle -- treat it as an event or let the
view just do it.
Where should the view related logic go? Let the Presenter figure out
what is null and what UI to show. Or let the view take care of it?
What should my over all focus be? Controlling the app with the
presenter, unit testing, both?
Very good questions, but, unfortunately, they do not have definitive answers.
It boils down to the fact that MVP (or any other MVx) is not a specific implementation, but rather a high level architectural pattern which is subject to interpretation.
Said that, my answers to your questions:
I'm a strong believer that UI logic doesn't belong into Activity/Fragment at all, therefore MVx views should never be aware of lifecycle events.
UI logic goes into standalone class that takes on responsibility of MVx view. Where you put null checks depend on the purpose of this check: if the result only affects UI (e.g. show/hide UI element) then perform the check in MVx view; if the result affects application's flow (e.g. show prompt dialog, change screen, etc.) then perform the check in the presenter; if both - perform checks in both presenter and view
Your overall focus should be on writing a maintainable code. Maintainable, first and foremost, means readable.
Again - the above answers are IMHO.
You might also be interested in this series of posts that I wrote: MVP and MVC Architectures in Android

Should the Observing/Subscribing be done on the View or Presenter?

For example if there's an activity with a button(View). When this is pressed, it calls a Presenter method, this method gets an observable from a service(Model) - which could take a long time to reply with results.
Should the subscriber for these results be kept on the Presenter? Then depending on the results, the Presenter would call the relevant View's actions?
Or should the subscriber be on the View? As I've been seeing in these other rx android example projects. In which case the activity/fragment would be calling other View or Presenter methods depending on the subscription's results.
The main goal of MVP pattern is to decouple the data access mechanism from view(activities, fragments). To make an application to be easily extensible and maintainable we need to define well separated layers.
If you return you subscriber on the view then it will break the MVP pattern. You should make your view as dumb as possible. So you should subscribe on presenter layer and let the presenter layer decide what should be the next step in the view. There might be some situation arise when different kinds of action might happen on the view. That logic should not be present on view.
**NB:This is just a suggestion. Make your view dumb. But you have to decide how much dumb you will make the view based on the action it performs. For an example there is a button whose click event pop up a yes/no kind of dialog. You should not call the presenter that the button clicked and let it tell the view to open a dialog.
But the situation you describe above you should use a presenter layer.
Presenter should do all the logic and heavy lifting while view is simple as possible. It only registers user input and, after all is done, shows the results.
Should the subscriber for these results be kept on the Presenter? Then
depending on the results, the Presenter would call the relevant View's
actions?
Yes, this is correct way to do it.
I would suggest to always keep subscription on Presenter. If View is allowed to 'see' the Model, it should only interact with Model in some simple manner such as data binding and simple validation. Otherwise, View is dump, Presenter proceeds all business logic.
Passive View and Supervising Controller are two variants of MVP for your references.
Please also checkout a new MVP framework for Android at http://robo-creative.github.io/mvp. Samples on there explains the difference between those variants. Have fun!

Multiple Activities / Fragments and the Model View Presenter pattern

Firstly, I know that with Model View Presenter there are different implementations, and in my mind as long as you have the layers of abstraction clearly defined and doing their appointed roles then how you implement this pattern is open to interpretation. I have been implementing this pattern in quite a few apps where there was just one Activity. I've now started a new project that has multiple Activities and attached Fragments, including nested fragments (ViewPager).
I'm now trying to translate the MVP to this project and I've hit a concept wall and would like some guidance and insights.
So far I've created the above structure and started to do a 1 : 1 relationship with View & Presenter (regardless of Activity or Fragment). I feel that this is OK, however if for example I sent a request to do something from an Activity View to its Presenter, which returns a result to the Activity View how would I go about propagating the result i.e. update all the other Activities/Fragments that are currently not in a Paused() or Stop() state. I feel like in this case there should be a central Presenter that updates all necessary Activity and Fragment Views, but I'm not sure how to go about doing this.
Currently when each Activity and Fragment is created it creates a new instance of a Presenter class, passing in itself as a reference (the Activities and Fragments implement their own interfaces), which the presenter stores as a WeakReference and can invoke the relevant interface methods when returning a result.
According to the docs whenever Fragments want to communicate with one another and the attached Activity you should use a callback interface. With this in mind should I have one callback interface that the Activity implements and the Fragments callback to whenever they request something, so in essence only the Activity would have a Presenter and Model layer that the Fragments have to callback to in order to make various requests?
Sorry if this sounds a bit muddled, hopefully this is clear enough to understand what I want to achieve, and if I’m thinking along the right lines... or totally off the mark!
I think this is okay to have a presenter inside activity. Basically activity is like a controller, it should know about the presenter.
It would be wrong to put a presenter inside a fragment if activity or other fragment needs it too. You can put a presenter inside a fragment only if this presenter is designed specifically for fragment.
which the presenter stores as a WeakReference and can invoke the relevant interface methods when returning a result
Why do you need a WeakReference here? If you have 1:1 relationship then I assume your presenter does not have it's own lifecycle, meaning that it's lifecycle depends on either activity or fragment. There is no risk of having memory leaks because it's not a singleton, right? It should be safe to have a strong reference.
I'm not sure if I answered your question because it looks a bit broad to me. My point is that, fragments are just separated "parts" of activity and you should treat them as parts. If presenter belongs to this part only, then it should be inside. Otherwise it should be in activity. You are right about using an interface to access activity, this is a well-known design approach which Google uses in their examples.
Nope, no interface anymore. You either use RxJava Observables to update all the views as described here or some kind of Bus(Otto-deprecated or EventBus). And you will like it because they make interacting too easy.

Categories

Resources