So here is a very standard task in Android: load data from the server and display it on the screen. One of the biggest problems is, of course, handling configuration changes. For example, when loading is started and device is rotated, the loading must not be started again and loading progress must still be shown.
Now, there is a ridiculous number of ways people approach this basic problem. Let's say, we use the Model-View-Presenter pattern. A lot of solutions revolve around saving Presenter, entirely or partially (in the View's bundle, in a Singleton or any other way), to not lose data on rotation. Others involve Retained Fragments and AsyncTasks. And I quite rarely encounter a solution that uses a Singleton to perform loading data! Why is that?
Here's the way I think it can be easily done. We make Presenters "light" and not perform any state saving, and handle data loading in a Repository that is a Singleton. When device is rotated, the newly created Presenter can just get current loading status from the Repository, update its View accordingly and, if data is loading, resubscribe to the Repository (via callbacks or RxJava Observable) to get notified when data is loaded. As for the Repository, it can easily load data in the background with the help of RxAndroid. So, isn't it easier to handle all data loading business in one place and not worry about activity's lifecycle?
This way we basically skip the whole configuration change problem. There are only a couple of things I see that must be handled carefully:
Activity leaks in the Singleton. To prevent this we just have to unsubscribe Presenter from the Repository when its View gets destroyed.
Testing, as it is harder to test a Singleton. But this is not an issue if we use Dagger - in this case we can test out Repository like any other class.
So my question is this: why is this approach (performing data loading in a Singleton) is not a common solution? What am I missing?
I seriously recommend you read up on a library specific for the purpose of network requests, rather then trying to reinvent the wheel and having to deal with all the pitfalls which might arise.
Recently I've been trying out RoboSpice. If you read up on their page below, you'll see that it "executes network requests asynchronously (in a background AndroidService)", precisely to avoid memory leaks.
I say, give it a try! Lots of projects in my workplace make use of RoboSpice and they all work pretty well.
https://github.com/stephanenicolas/robospice
Related
I'm using Android Room and combination of LiveData in my app successfully, but I notice it has a significant delay between query and presenting the data to the UI. It is not the end of the world, not unsustainable at all, but when opening other messaging Apps (like WhatsApp) the difference is monumental. When I open such an app the conversations and messages are already available, there isn't even time to play the fade in default animation that is typically available in RecyclerView lists.
On the other hand in my app I can clearly see the delay the data takes until it is presented to the UI.
I understand that attaching the viewmodel to a fragment means that same viewmodel is reconstructed every time the associated fragment is rebuilt, so in theory attaching that viewmodel to the activity's would mean that data would survive even longer in memory, thus saving loading times when rebuilding the fragment, but the very first time it loads it still will show that significant delay, so this isn't an ideal solution nor do I know if this would be an ill advised modification (attach the fragment's viewmodel to the activity lifecycle instead of fragment's).
Are there any ways that I can improve this? Is perhaps WhatsApp using a completely different SQLite library that is marginally faster than Room so I will never be able to achieve this performance with Room?
I think, you have to investigate the issue before try to fix, possible bottle necks:
slow database queries
reasons:
huge amount of data
not optimized queries
middleware converts (if you use it)
Just calculate a middle time for 5-10 calls.
slow UI drawing
check your RecyclerView or other UI.
Use AndroidStudio profiler to find out potential slow code.
I'm rewriting a simple application to use the MVVM architecture. I got everything working, except retaining state when the user rotates the screen (or any configuration change for that matter).
While doing research I've come across several options, but I can't figure out which one is right (if there even is only one "right" way).
(onSaveInstanceState: can't be used in the ViewModel, this only works in activities/fragments)
Extending the ViewModel class. This is apparently made to make it easier to store UI-related data across the lifecycle. I find it quite confusing, and it seems overkill for what my app does. There are no async requests to online databases, feeds, or whatsoever. More than that: I can't use #Bindable anymore, so I don't know how to make the binding with my View.
Using fragments to persist state. This is used in Google's own todo-mvvm-databinding sample. I find it strange to use Fragments for this. They don't seem to be made for the purpose of just storing data.
Which one is the "best"? And why?
I'm confused in finding a better way to implement:
1) data caching, as I am fetching data from rest APIs by executing AsyncTask in every fragment say 3-4 times, what I want is to reload the data from cache instead of calling the AsyncTask again.
2) a way to deal with configuration changes events... such as orientation change or some other events.
confusion: are DATA Caching and onconfiguration changes related at all somehow? If so, does only caching code can serve the purpose for both issues?
What I've tried : here's a project that does the magic for onconfiguration changes part and
this library project can serve the data caching purpose
or should i use the volley library as recommended in google io 2013?
My MODEL: I am having 1 ACTIVITY that controls and seven other specific fragments that does the execution part. Please type your words if you've any kind of idea how to proceed?
Loaders may totally satisfy your needs. If not, consider using LruCache.
I'm currently attempting to convert my existing Android app to using Fragments. The main work that my activity does can sometimes take a while, so I implemented some Threads to act as callback handlers - I was led to believe this is best practice to use these and a progress dialog.
Hopefully that makes sense.
My question is: should I move those inner classes to my Fragment class, or keep them in my Activity class?
That depends how many fragments you have and what you're trying to do with those threads. While there is no general rule, here are two things to consider in making your decision.
(1) If you're doing something like downloading information that's going to be used in multiple fragments (say in a ViewPager or Tab set up) it might make sense to have the callbacks in your FragmentActivity this way you can easly distribute that information to the Fragment that will be handling the UI. Another example that comes to mind would be fetching location data. If the location data is going to be used throughout the app, and your FragmentActivity is hosting multiple fragments, it makes more sense to get the information in one place and simply update the fragments individually.
(2) If you're using something like AsyncTask for one-off downloads, posts, or other things unique to a specific fragment, there's nothing wrong with keeping it localized to that fragment. In fact, in that case, it would be less efficient to off load the task to your FragmentActivity than to complete the task localy.
Really there's not "right" answer. Just a question of how your app is structured and what you're trying to acomplish.
Actually the best practice for software in general is a little different, first of all you need to know that there's no "Hard Rules" to anything in software, the keyword is "All Depends(Taken from book Pragmatic Thinking and Learning)" and as such, it all depends on what you want and what you need, you should put things on a balance to know where is better for you, but going back to the best practice in general for these cases the best is to have a Business Model Class completely decoupled from either Fragment/Activity or any other android component, you are actually supposed to have a Model Class and together with a Controller Class, both of them should manipulate/populate the data and views within those elements...
Hope this helps.
Regards!
There's no hard and fast rule, but I like keep them in the scope within which they most naturally fit. If the result of a long running task is only useful within the fragment which initiated it then it lives in the fragment. If the task may affect multiple fragments then it might live in the activity.
Are there any advantages of Loaders over Async task? Also, how to make loaders compatible for phones with Android froyo.
Edit:
The primary problem here is that I'm not using the native DB(SqlLite). Using the DB on development server. Obviously, I can't use CursorLoader any more. AsyncTaskLoader has no examples at all. If any, please do link.
Is it a better idea to load the data required onto the local DB and then query it using CursorLoader?
Yes, Loaders are more advantageous than AsyncTask as they take care of a lot of things that AsyncTask falls short of, miserably.
Screen Orientation changes are difficult in AsyncTask. I used to have such a problem, till I used an Activity Control class, which I used to retain while configuration changed. I can give you some code if you want to know how. The app used to crash, though, when you changed the orientation multiples times even before the entire data loaded. The secret here is not load a lot of data with your first thread and and finish your threading tasks as soon as possible. Even if it happens in the background, Android has a shabby way of dealing with threads. You never know when one of your tasks would be killed.
Even if you use a AsyncTaskLoader, makes sure that you use an Activity manager. This will help you in getting more control over the activites and AsyncTask.
Yes, it is compatible in all the old version of Android. You need to include the support library(Most of the times, this is included by default but its always nice to double check.)
For one, loaders are easier to code (they're almost built-in in Fragments).
Loaders (specifically CursorLoader) also handles your cursor for you (like the deprecated manageQuery).
Check out this link to read on how to use Loaders pre-Honeycomb.
There simpler to implement and take care of a lot of the life cycle management which previously had to be done "by hand" with AsyncTasks. See the answer to this question for further detail.
With regards to using them with Froyo, they're available via the compatibility library.
It seems no one is talking about the disadvantages of loaders! I'm currently working on a system that runs other services in the background.
What I have noticed is that as soon as a screen with a loader is resumed. The cursor used by the loader locks up the DB.
It may not be open to most people but getDatabaseWriter from sqlite is actually a synchronized method and hence the cursor used by the loader is never closed until the loader is reset or terminated thus locking up access to the DB.
I cannot recommend using a loader under these circumstances nor can I advice using a loader when your result set consists of less than 100 items which are static and never seem to change.
Another advantage with loaders is that they handle screen turn event gracefully whereas asynctask can give you trouble.
Biggest diff:
CursorLoader will update your UI's content as soon as its related ContentProvider changes its content(say through a Service), while AsyncTask will only update your UI when you tell it.