Sorry for the huge post, but for what it's worth, every app that I do 
nowadays has the same general pattern...

I basically have a model class(es) that incorporates any logic or data that 
you don't want cluttering up your views/activities/fragments and where you 
would do any networking stuff. By model I mean the M in MVC or the M in 
MVVM or the VM in MVVM. (Let's say an account object)

You can inject this model class into your views/activities/fragments when 
you need it - using dagger or you can just roll your own dependency 
injection code via the application class.

That means that the fragment/activity classes just manage their lifecycle 
and get references to whatever models they need (an account object, maybe a 
network state object or whatever) and do as little else as possible.

When you update the UI, you just run a syncView() method on the fragment or 
your custom view class (my preference, as it removes even more code from 
the fragment) that sets the state of all the UI components eg: 
textView.setText(account.getAccountName()); you just need to make sure all 
the get() methods on your models return immediately.

Any network connectivity or other stuff that needs to be done on a separate 
thread, I would do from the model class which mostly exists independently 
of any activity/fragment lifecycle (saving you a whole heap of lifecycle 
trouble).

Once the network stuff has returned with data or an error to the model 
class, I use the Observer pattern so that the views/activities/fragments or 
other models that are interested, get notified of the change to the model 
and then update themselves based on the model's new data (see the 
syncView() method above). You can roll your own simple observer classes (my 
preference) or use something like RxJava or even Otto can be used this way. 
Also if you send all your update notifications on the UI thread, you'll 
save yourself some headaches when updating UIs based on them.

So the models themselves will make use of Volley or Retrofit/OKHttp (both 
are pretty good and I would definitely use one of them) and may have 
AsyncTasks in there too. You just have to make sure (especially when using 
AsyncTasks) that you can independently test the models which means being 
able to inject the networking stuff (substituting mocked versions for 
tests). The way AsyncTask is designed makes it particularly awkward to 
test. You can: Write complicated tests to handle the threading problems 
using a latch and so on; Test only using a framework like espresso (but 
then you will be testing via the UI and not strictly doing a unit test; Or 
you can wrap AsyncTask in your own class that can be used in a synchronous 
way for tests - that's what I do and it makes the tests much simpler.

If you're fetching lists of stuff, I'd use the model classes to write 
straight to a database once the data has been fetched from the network. 
ContentLoaders while they do clutter up your fragment/activity code, do 
seem nice and performant and have a built in observer style mechanism so 
when the data in your database changes, your view gets immediately 
refreshed. You do have to write a content provider but personally I think 
it's worth it.


I just realised how complicated all of this sounds, but it is actually so 
much simpler than jamming everything in your activity classes, which is 
just crazy but very common to see. I think it's a major failing of Android 
(as opposed to iOS or windows phone, or maybe most other application 
platforms!?) that it seems to have been designed with no thought about the 
absolutely fundamental issue of how you should separate models from views 
or how you might test your code.


http://en.wikipedia.org/wiki/Observer_pattern
http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf

-- 
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Android Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to