
EasyMVP – Android library with annotation processing and bytecode weaving - joblack33
https://github.com/6thsolution/EasyMVP
======
StavrosK
Can someone explain what these are? I'm not familiar with Android code.

~~~
BoorishBears
The Android ecosystem is a few decades behind the rest of the development
world for design patterns because, to frame it in web technology, every time
you resize your window the entire browser restarts and its up to your page to
restore its state (Activity/Fragment = Page)

People were so busy fighting that mess in the early days they ended up writing
a lot of shitty code.

Then Android has reached where programming was after Smalltalk came out, about
a year ago when MVP became "that exciting new way to write less shitty code"

No one really knew what MVP was but they had to have it.

Then someone stumbled upon Uncle Bob and everyone needed to write "Clean code"

Google threw a wrench in things by releasing its data binding library which is
MVVM so now there's the holy wars over that on the horizon.

And everyone is doing MVVM bindings the way everyone else figured out was
wrong in the mid 2000s (using your bindings to do business logic) so it looks
like MVP is pulling ahead before the war even starts.

So this library is for MVP that works around the whole "reopen the browser"
issue because your presenters get killed when the browser restarts.

~~~
StavrosK
Wow, great explanation, thank you. I thought mobile programming was at the
cutting edge, given how much code and focus there is on mobile apps. I'm sad
to hear it's exactly the opposite.

I would have imagined mobile devs/languages would have nailed asynchronous
programming by now, since mobile apps are basically one huge jumble of
asynchronous events and processes.

~~~
crla
I don't believe it is as bad as BoorishBears says.

Yes, configuration changes cause a tear down and recreation of your
view/controller layers, but there are several patterns to deal with this
cleanly (view controllers whose lifecycle spans multiple instance of a view is
one of the more common, with the view instances detaching/attaching as they
come and go). If you use a Flux like pattern for handling application data
state you don't even necessarily have to do that since your views are just
observing data stores whose lifetime outlives the views anyway.

As for asynchronous handling, there are quite a few popular libraries that are
very powerful and make it easy to compose multiple asynchronous operations,
update views on changes, etc - RxJava for instance has been pretty popular for
the last couple of years and is very powerful, but has a steep learning curve.
There are others such as Agera (from Google itself), as well as simpler async
libraries like Bolts (similar to .Net task futures).

The Android SDK itself does not contain much in the way to help with any of
this though (I would avoid pretty much any of the async classes that come with
the SDK such as Loaders and AsyncTask) - so you do have to research and learn
about third party libraries to get to a state where you can write clean and
concise code.

~~~
BoorishBears
Don't get me wrong, I don't mean to imply writing clean apps is impossible but
I believe it's a fair assessment of the "state of the Union" for development.

Even your comment kind of alludes to the mess:

Yeah there's RxJava but it doesn't inherently solve the rotation issue because
your Observables so you still need to persist the information needed to
recreate them. And any long running tasks need a separate solution because
tearing down the Observable will reset the operation

Googles app development team made Agera which was widely panned as an inferior
NIH RxJava

Having your view's controller persist also requires custom logic because only
your application will persist through configuration changes and even then the
process can still get killed leaving you with nothing but data stored to disk
via Parcelables or your own custom solution.

Android Devs solved asynchronous operations, the problem is keeping those
operations going after a configuration change. If the operations reference the
view you'll get NPE when the view is destroyed while a job finishes, and if
your view references the operation you need to lay down infrastructure to let
your asynchronous operations exist completely separate of the view and be able
to cache their results for when the view comes back.

It's not impossible, everyone does it somehow, but it's created a lot of
divergent theories on how it can be done

~~~
crla
I also think the Activity handling of configuration changes was a mistake; it
should have only ever just been the view that was recreated.

However, I don't think that in the end it's that horrible, once you overcome
the learning curve.

If your process is killed and the user returns to the app, you have to be able
to restore state from either the Activity's saved instance state or from some
other form of persisted state anyway - whether the current approach to
configuration changes was in use or not makes no difference here, it's due to
the entire approach of the OS to killing and restoring processes as required
(and I believe this same approach is used on iOS and for UWP Windows
applications).

For handling of async results - once the owner of an async operation is not
tied to a single instance of a view and is instead tied to the overall
lifetime of that part of the application (e.g. retained Fragment, a Conductor
controller, or pretty much any other reasonably modern view composition
library), it's pretty trivial to handle. You're guaranteed that nothing else
will run on the main thread for the duration of an Activity destroy/recreate
cycle, so you don't need to worry about being in some unknown state. If the
view was recreated due to a configuration change, rebind your view model/s
when it attaches. If you're being torn down because the user left the retained
Fragment/Controller/whatever the operation was tied to, you'll receive an
indication of that and you can either send a cancellation signal (e.g.
unsubscribe), or if that's not possible, have an isDestroyed check where you
receive your result to ignore it. If you're on the back stack and still alive
but have no view (i.e. view NPE), don't bind your model immediately - update
your view model, and the same code you use to rebind on view reattach will
kick in when the user returns and a new view is created and attached.

~~~
crla
I should add - I do think the learning curve is much worse than it should be,
in part due to this.

It would be nice if Google provided some more recommendation and best
practices & patterns around this. I have come across and had to work on plenty
of code that handles this all very poorly.

