square / mortar

A simple library that makes it easy to pair thin views with dedicated controllers, isolated from most of the vagaries of the Activity life cycle.
Apache License 2.0
2.16k stars 155 forks source link

FAQ entry: when to call takeView() #73

Open rjrjr opened 10 years ago

rjrjr commented 10 years ago

Archiving this here until we get a real FAQ togther.

tl:dr; If we need them, we effectively have two display phases: initial render (takeView call from onFinishInflate) and an update pass (ping your presenter from onAttachedToWindow)

Standard practic is for a View to call presenter#takeView() in onFinishInflate(). This allows the presenter to set up the view before layout and measurement, and keeps things beautifully synchronous. This is all you need 90% of the time.

But sometimes you'll have transient state that gets clobbered by Android's view hierarchy persistance, typically model state that changed behind the scenes while you were elsewhere in the backstack. When this happens and you're tempted to use View#post to fix them later, stop. Take a breath. And instead ping your presenter from onAttachedToWindow().

pforhan commented 10 years ago

For completeness: how do you "ping your presenter" -- a custom method, right? You shouldn't ever repeat takeView, etc.

imminent commented 10 years ago

You wrote "seens", probably want "scenes". The other use case I had for not using onFinishInflate is when it is never called for your View, which is the case if you create it dynamically. addView(new View()) will never trigger onFinishInflate() on the View.

loganj commented 10 years ago

@imminent Best practice with mortarmortar, maybe generally, is to use an inflater. You'll get consistent results with regard to styling etc. without having to think about it. There's a tradeoff there, but the consistency is well worth the verbosity.

ChrisRenke commented 10 years ago

My first reaction was to grab on at dispatchRestoreInstanceState or restoreInstanceState depending on if its a top level screen or a widget within a screen; gets the job done as well. Feels a bit cleaner than "waiting" for the attach, but always grabbing at onAttachedToWindow has a pleasant ring to it.

I had another case where I needed to trigger an animation of an ImageView from a fixed coordinate on the screen to a view on the screen; even onAttachedToWindow was too early because the destination view hadn't yet been laid out. To get a hook right when everything was in place, I kick off the animation via a ViewTreeObserver.OnGlobalLayoutListener set with getView().getViewTreeObserver().addOnGlobalLayoutListener(myListener); the listener is called when the view has had a layout and thus everything has been placed in its proper place.