Android MVP best way to handle views with API call - java

I am having a question regarding how do I update my view or perform a fragment transition when the view goes to background and the API response comes as a callback.
For example I have a loginfragment. User clicks login button and the presenter takes it and gives it Interactor where I have my Rx observer who talks to repository and model and so on. The response comes back in maybe 3 to 5 seconds. Within this time, I press home button and my app goes to background. The presenter receives the response from Interactor callback and now wants to update the view but view is in background.
On login success, I want to make a fragment transition and go to Fragment B. But my view is in background. So when I bring my app back to foreground, I still see login screen although I already got a login success API response.
How do I handle view updates or fragment transition when view goes to background and what is the best way of doing it?

One approach is Model-View-Intent architecture in Mosby, in which the presenter stores the latest state of the view, and the view subscribes to the ViewState Observable in order to update. In such approach the view can subscribe in onStart(), when it is safe to make fragment transactions.
Another possible approach is that each view has a state (ViewState), that holds a queue of commands to the view. If the view is ready (onStart() was already called), then the command is passed to it immediately, otherwise it is saved to a queue and postponed until the view is ready. See how it is realized in Moxy.

Related

Android best practice to handle UI during a network call

I want to know what is the best way to handle a UI during a network call. For example -
I have a login screen with login button and email and password input fields. I enter email and password fields and press login button. I show a progress dialog. I subscribe now with RxJava and I have my observer in presenter. He tells the view to show a progress dialog. The API call is in progress. Stil my observable has not returned anything back. Now I press back button and my progress dialog is dismissed. I again press login button and a second call is done. So I can do this repeatedly and queue my requests.
What is the best practice to handle this scenario where user is allowed to make one request per once button click? I know there are several ways to do it in view such as greying out the button or using a progress bar which is non dismissable. But I am more interested in knowing how to deal this scenario in my model layer. I want my view to be as dummy as possible.
Why not override onBackPressed to cancel any in-progress threads?

In MVP structure which class responsible for keep list items and how to notify data change in this

I trying to refactor one of my activity class to implement mvp(using mvp mosby library) . I have a RecyclerView and in this view there is some items that some changes apply to them during the run time. for example I do some I/O operation and change one row.
I think it's better to keep my items in presenter class; what is the best practice for this? keep this in 1)presenter or 2)activity or 3)only keep view related item in adapter and all other item in presenter.
the activity now keep items directly and change item row in activity and then notify adapter. isn't better to move all this line in adapter and notify adapter in the adapter class? for example i want change icon of some row.where and which class is responsible for that? adapter? activity? now I want to implement it like this in adapter:
changeItemIcon(int position, int iconRes){
mImages.get(position).setICon(iconRes);
notifyItemChanged(position);
}
I invoke this method on activity and invoke activity method from presenter.
is it good? what is the best practice to do this?
UPDATE
also I find this question ( Best way to update data with a RecyclerView adapter ) that using adapter method for changing items. but what about modify? Need I keep reference to items in my activity?
for example i want change icon of some row.where and which class is responsible for that? adapter? activity?
I know it sounds a little bit strange, but changing an element is always the responsibility of your "business logic", even just for "icons".
The workflow should be as follows (unidirectional data flow):
View appeares, tells presenter to load a list of items
Presenter loads items form "business logic" and registers himself as an
observer / listener / callback (whatever you want to call it)
Presenter receives result and tells the view to display the list of
items (through RecyclerView and corresponding adapter).
so far is what you have implemented I guess, now it comes to the point where you want to change an item.
User clicks on an item in your RecyclerView which then should trigger to change the icon of this item. Therefore View should call: presenter.changeItem()
Presenter is just the man in the middle in this case and will invoke the "business logic layer" to tell that the item should be changed to new state (icon has changed).
"Business logic layer" will change the models state (change the items icon) and then will notify its observer / listeners that the model has been changed.
Since Presenter is still observing / listening to the business logic layer (see point 2.) the Presenter will be notified (see point 6.) with a new (updated) list of items containing the updated item which icon has been changed.
Similar to point 3. Presenter will tell the view to display the new (updated) list of items (through RecyclerView and corresponding adapter).
Do you see the unidirectional data flow? That is very important. Immutability FTW.
MVP has two different variants: Passive View and Supervising Controller. Depending on your taste, you can stick to one or mix both of them in your app.
If you choose Passive View, you need to hide Model from View and let Presenter format data then set to the View. In this case, you need to keep Model reference in Presenter. View should only hold view-data (adapter) for its displaying purpose.
If you stick to Supervising Controller, you can allow View to directly bind data from Model and ask Model to perform some simple logic. Presenter should only care complex logic, i.e some operations which need to involve Services. In this case, you can give Model (your items) to View (activity) and let it interact with Model in some simple manner.
PS: Please also check out our new MVP framework: Robo MVP at http://robo-creative.github.io/mvp.
I've never used mosby, but I've just read their docs (good reading btw) and here's my understanding:
A recycler view usually consists of the view (android term) and an adapter. Both are connected inside a fragment or activity. In terms of MVP/mosby this is all view layer. The presenter should only retrieve and pass the to-be-shown data from your service (model layer in mosby, "service layer" or "business logic" in other concepts), which in turn gets it from a DAO or repository (model layer).
The docs say that the presenter only handles the view state, not the actual contents. Your state is "showing list".

Connection between activity and layout? How to change layout? How to start and destroy an activity?

I'm a total beginner with Android and Eclipse and I have few questions that will help me understand the philosophy of Android:
The activity does all the work "behind the scenes". Activities are connected to a layout in the XML file. When the activity is started, if declared in setContentView method, the connected layout will be shown. Activity can be independent, without any layout, it can be invoked by another activity and will do all the work without showing any layout.
Activity is something like a php file which is invoked by my submit button in HTML, and the layout is .HTML which shows elements.
Am I right with this one?
For example, if I want to change the layout of my app, I want to show Layout2.xml when clicking button in Layout1.xml. Then I have to destroy the activity which is connected with Layout1.xml and start the activity which is connected with Layout2.xml? Is this correct? Is there any better way to do this?
How can I (by which method) destroy/stop a certain activity?
Thank you in an advance.
The best bet is to read the Android documentation regarding activites at http://developer.android.com/reference/android/app/Activity.html
I will answer your specific questions here though
An Activity is a window that the user can see (or a hidden window if there is no layout defined). It deals with the logic of a part of the app that the user can see and interact with. If we take the MVC model (Model View Controller), the Activity is the controller, in terms of it controls which data from the Model is shown on the View (the xml layout).
If you want to show a new window/screen/activity you do not need to destroy the current one. You can open a new activity whilst keeping the old one in the background (in the back stack). With the use of fragments, you can have multiple fragments in an activity so rather than changing activities, you can change fragments in a single activity. For more information about fragments take a look at http://developer.android.com/reference/android/app/Fragment.html.
This point relies heavily on the activity lifecycle. When an activity is destroyed, it means it is finishing and this can be done by the user pressing the back button whilst on the activity, the activity calling finish() on itself or by the Android operating system destroying the activity because memory is required elsewhere (this can happen when the app is in the background).
When we say an activity is stopped, it means that the activity is no longer visible to the user. This can be the case where the activity is in the back stack (another activity is in front of it) or if the app has been put into the background.
This is a brief answer to your questions but I highly recommend you read the Android documentation to gain better knowledge.

ListView and updating the Adapter when Activity is not visible results in poor performance

I have a performance problem.
So I'm writing a chat application and I have a ViewPager with Fragments in it for each separate chat, the ViewPager lives in ChatActivity, and the messages in the Fragments are displayed via a simple ListView.
Everything is smooth as long as I "minimize" my application. When the app is minimized, and I receive, say just 10 messages during that time, and return back to the activity, there is a noticeable delay (e.g. the standard Android Application restore animation does not play). If I minimize the app again, and restore it instantly, the delay is completely gone (assuming no new messages arrived).
There seems to be no correlation in the performance to the amount of new messages that have arrived: whether there are 10 or 500 new messages, the delay is the same.
I receive messages from a Socket, pass them to the Chat object, which simply passes them to the ChatFragment, which just uses listView.post() to post them into the ListView.
My ChatFragment and ListView's adapter are pretty trivial so I don't post them here, the messages are stored in an ArrayList in the Chat object (the adapter just pulls them from there).. I'm really not doing anything "fancy".
To put it simply, when my Activity (and the Fragments in it) are paused, and new data is posted to the ListView, the ListView (I assume) has to do "more work at once" when the Fragment is resumed and the ListView is "refreshed".
This might be a bit vague without code, but perhaps someone can tell me if my principle is at least right (i.e. simply post() the messages to the adapter, regardless if the Activity and Fragment are visible to the user?).
If anyone has any ideas what might cause this delay, I'd be very grateful.
My intuition about new messages and the ListView problem was completely wrong! What caused the slowdown was that I have a launcher activity that launches the previously visible activities or displays itself if there isn't one. Instead of calling finish() in the onCreate() of it, I simply called return! This caused the activity to go on with its lifecycle, doing whatever it does behind the scenes, causing the slowdown.

Change view in activity

I have an activity that sets a custom created view "onCreated" and a Thread is started, this thread cycles every 23ms and "invalidates" this view so it's onDraw is called almost always.
This view continues in screen until a user clicks on it (onTouchEvent) and view does some proceses and when ready a public flag ins enabled so the activity "knows" when the view was activated and has made it's proceses, in this moment the activity should change it's view to another one custom created, the problem is that because the flag checking is done in the run method of the thread the activity sends a "CallFromWrongThreadException", this is because as far as I understand the "changing" is in another thread (not UI).
I have set the runOnUiThread to overpass this and the srceen goes completly black.
Also I have tried to set the activity to a framelayout in which I add both views at begging and the thread changes visibiliity of the views, no success at all.
All view manipulation must happen on the UI thread. There are a few ways to do this. One is to use AsyncTask to perform your background work, as it has means to run code on the UI thread after the background work has completed.
Another option is to post the code you want to run through the view itself, like this:
mMyView.post(new Runnable() {
public void run() {
mMyView.doSomething();
}
});
This method would work well for toggling the visibility of an existing view.
This is a good overview of these methods: http://android-developers.blogspot.com/2009/05/painless-threading.html

Categories