reset Android FrameLayout object to "clean" state - android

I am trying to implement my own Android view recycling. My question is, is there a simple way to "reset" an Android View object (more specifically, a FrameLayout) to the state in which it would come out of a constructor. In other words, it knows about its context, but it's forgotten about things like calls to SetWillNotDraw, touch handlers, visibility, or anything else I may have set on it.
The alternative would be to write my own "reset" method. I'm concerned that if I go that route, I will end up with bugs relating to failing to reset some portion of the state.

No, there isn't. If you weren't trying to do recycling I'd suggest just creating a new one is the easiest way to ensure it. Its also not a very efficient thing to do in general- there's a lot of pieces of state that can be changed, if you try to set all of them you'll end up wasting a lot of cycles. Generally you have the code that sets these things have a reset method of some sort called when you unbind a view from its model, and it will clear the subset of things it changed.

Related

ScrollView vs RecyclerView for dissimilar children on Android

I have a mix of 10-15 custom views and fragments to be shown in a vertical list. I am not sure if RecyclerView has any advantage in scenarios where all views are dissimilar. RecyclerView seems to add lot of boiler-plate code, and I think the only advantage I would get is easier enter/exit animation.
My custom views/fragment also make web-service call on being created. We don't cache web-requests for business reasons. My understanding is that RecyclerView would trigger these web-service calls on each binding, resulting in redundant calls and visible latency. Comparatively ScrollView should load the views once, and it keeps them all in memory, avoiding multiple calls.
Is my understanding correct ? I need some help understanding performance implications with ScrollViews, in the given scenario.
ScrollView
With a ScrollView, all of its subviews will be created at once, regardless of visibility on screen. If using a ScrollView for your solution, you'll probably want to "listen" for when its subviews become visible to update their content, using placeholders initially. You could also build something that will fetch the content in a background thread. This may get more complex than you want very quickly.
RecyclerView
A RecyclerView provides the advantage of deferring creation of child views until they become visible automatically, and can re-use child views with common layouts.
By using different "item view types" for each of your children, you'll disable the "recycling" part of RecyclerView, but still get the benefit of deferring the creation of views until they are scrolled into view.
RecyclerViews do provide a fairly structured pattern for you to work with via the Adapter and ViewHolders. Though not personally familiar with it, RecyclerView also has a RecyclerView.ViewCacheExtension which is intended to give the developer control over caching of views.
Overall, the advantage of late binding (don't create and load views that might never be viewed) and the flexibility of the RecyclerView will probably yield good results for you.
First of all you have to decide what you are using View or Fragment or maybe both. Don't compare View with Fragment there is a common misconception about these two, they are not similar, actually a Fragment is close to an Activity in terms of architecture and implementation.
Second, can you reuse some of these View/Fragment, if yes, then RecycleView can help you a lot.
After you decided about the topics above:
My understanding is that RecyclerView would trigger these web-service
calls on each binding
No, this is not true, the binding method is called whenever a new item is displayed (reused or newly created), you can implement adapter to perform the web API only once on an item, this is your choice.
I always go for RecycleView/ListView whenever possible, it helps to reduce the memory footprint and can reduce the implementation. In some cases, where there is no huge memory usage on views and I can't reuse some of the implementation, then I go for ScrollView, but I think twice before implementing it.

When to use ViewStub vs Inflate?

The article http://android-developers.blogspot.in/2009/03/android-layout-tricks-3-optimize-with.html talks well about when to use View.
But I did not find a use case where I should replace the Inflate with ViewStub.
I didnot see any performance improvements when I replaced inflate with ViewStub.
Essentially ViewStubs just offer another way of doing things, or "achieving your goal". I find that you'll learn to use them when you are stuck and looking for help or another option. Otherwise if your code is doing what you want correctly without ViewStubs, then just forget about them for the time being.
There is no point forcing yourself to use extra options when you don't need them.
ViewStubs, in my own words, are "use once", temporary type of view holder. Use them when you want something to become visible on the screen only for that Activity's current life cycle.
There are other way you can accomplish that, but ViewStubs are very lightweights and simply offer a slightly different set of pros and cons compared to normal View objects.

How to detect when a view is being removed

I have built a simple system that allows the user to update views throughout the application whenever a linked image file on disk has changed (the App has a bunch of drawing operations that let you change the images).
It works by maintaining a list of FileUpdateListeners which contain a File and a View. Whenever a SaveTask is created for a File, it will run through all the listeners and call any listeners hooked to that File.
Now it appears the Views are constantly dropped and remade as you move forward and backward through Activities. However, the listeners all stick around. I´m guessing because their reference to the View prevents it from being garbage collected. I´m pretty sure this is going to wreck the performance and eventually cause the app to run out of memory.
So my question: Is it possible to detect when a View is unhooked from the Activity, so that I can remove the Listener that it belongs to? Or is there another way to make sure the Listeners are removed when the Views are removed?
Ideally, the Listener should not be inside the View. I'd want the system to work with any kind of View.

Activity fragment in expandable listview?

I'm looking for any examples or (even better) tutorials that can help me accomplish this. But I keep coming up short in my google searches, which has me worried that it's not even possible. So that's my first question: Can an expandable listview inflate a fragment when it expands and call it's onDestroy when retracted? and if so, can you please link me to any help with accomplishing this. Thanks
Here's a little visual of what I'm looking to do:
first, the general UI paradigm could be handled with an ExpandableListView. whether this gives you enough to match exactly what you need is TBD.
as for having fragments inside the list ... theoretically, in the list view's adapter's getView() method, you could do a FragmentTransaction.replace(), passing in a container ID that exists in the inflated view. i have not tried this.
that being said, i seriously doubt this will work. list views are smart about managing views. the views in the list are often destroyed and re-created as the user scrolls the list. adding fragments to a view is an expensive operation.
as an alternative, you might consider a ViewPager, which can hold fragments by design. it's not the UI you have spec'd above, but it's a common UI pattern used by many stock Google apps, so you know it's been tested.

Why use the word "invalidate" to request a view to be redrawn?

In GUI, when a view is required to be redraw. We usually do this as follows:
View v = View ();
v.invalidate()
I have no idea that the operation "invalidate()" is such named. In English, "invalidate" means to make something not valid. But "invalidate a view" in GUI programming is meant to make the view to be redrawn. I am not a native English speaker. Please give me hints. Tks.
To "invalidate a view" means that any data that may already be drawn is no longer valid. The view of the data is invalid, hence invalidate() to mark it as such. It's less that the function is making it invalid so much as it is already invalid, but no-one except the caller to invalidate() knows that yet. The purpose of the function is to tell the rest of the code that the views data is now invalid.
Invalidate is semantically different from redrawing in that it usually only marks something to be redrawn later, as opposed to redrawing at call-time. The idea is that when several possibly overlapping areas are invalidated, the amount of redrawing at a later time can then be made equal to only the sum of non-overlapping areas. That is, we may redraw only once for several subsequent invalidations. Hence the distinction between redrawing and invalidation exists.

Categories

Resources