I wanted to know whether the onDraw method get called without the programmers knowledge. I know that it is called at the first time View is loading and I know it calls when I call invaliade(). But does it calls in any other times?
Yes, whenever a parent view is redrawing itself like if the custom view is within a ScrollView whenever you scroll it...
Related
According to concept of recycling items mechanism in ListView.
I want to know, actually, how i can detect a moment when a View going off-screen.
I explain why.
In most cases ListView have a custom
Adapter(? extends ArrayAdapter / ? extends BaseAdapter, etc.).
getView(...) method allows to manipulate visibility and content of views (text,bitmaps,drawables,etc.)
And in some cases i need to launch a separate Thread which doing background work, and after that update UI. Actually - using AsyncTask.
When i have many items in ListView each call of getView will be produced start a new Thread. I need to cancel them if View is no more longer present on the screen. How to do this?
You can override onDetachedFromWindow for the view.This will let you know when the view is going off-screen.The docs says:
protected void onDetachedFromWindow ()
Added in API level 1 This is called when the view is detached from a
window. At this point it no longer has a surface for drawing.
See Also
onAttachedToWindow()
I have a background view not showed into main activity and I need to get the "invalidate" event for know when something into the view is changed.
The problem is the event "invalidate" is "emitted" by the view only if this view has been added to the main activity thorugh the "addView" call. I don't want to add this view to main UI since is managed in a separate thread but I have this problem of invalidate event not emitted and I don't know how to find a workaround. It seem the "addview" function unlock something that allow to generate invalidate call but still not found the reasons.
Someone know how to force a view to generate invalidate event also if not added to main activity?
I think you can't do this, because invalidate method is called by View framework, so this method would't be called if the view is not add to the window. But I think there's a trick: adding this view to the window and hide it below other view, so this view is invisible and the invalidate method will be called by system.
Why would you want to invalidate a view that is not there? Instead of finding a workaround I suggest to improve how your app works. Invalidate means that you want to redraw something that is on screen. I don't know your exact use case is but my guess is you want to do something that is not UI related in invalidate. You should not do that.
I implement a view by myself, the onDraw method of the view is called repeatedly. This will cause a serious performance problem. The code is so complex that I can't paste here. Anyone can tell me some possible reasons? I haven't touch the view by my finger.
One reason would be that your onDraw method is calling some method that (perhaps indirectly) invalidates the view. Another possibility is something completely unrelated in your program is causing the repaints. Try this experiment: comment out your drawing code and substitute something really simple, such as a simple line draw, just to show that it's working. If the repeated drawing goes away, then it's something in your onDraw code. Just start restoring the current code a bit at a time until the problem reappears and then you can track it down.
If the problem doesn't go away when you try the experiment, then look somewhere else in your code for something (perhaps a worker thread?) that is invalidating your view.
I had the same problem today. I solved it by overriding invalidate() in my View subclass:
#Override
void invalidate() {
super.invalidate();
}
Then I set a breakpoint inside invalidate() and waited for it to hit. When it did, I had a stack trace of the call, and the offending caller. Mystery solved in 2 minutes.
If that doesn't work, trying overriding the other invalidate methods in View.
I have a custom view which extends View. I am adding this to an activity as setContent(..) after creating its object, but its onDraw() is not getting called more than once. I know that it should be called infinitely.
Any idea why this is happening?
Android 2.2,2.3 tends to call onDraw a lot more than 3.0 and up.You should call onDraw yourself ,or invalidate() , when you want to create an animation or something and don't call it when you don't.
I have a ListView with custom Adapter. To be honest, I have many of them at the same time on screen, and my Tegra 3 device started to lag, what made me really confused... I found than in each ListView's Adapter the getView() method is called for all visible rows every time any animations runs on screen. That gives me like few hundreds of calls per second! Digging more, most of these calls are due to measure() and onMeasure() calls of ListViews' parents, and - this is tke key - they are useless, because all the layouts of my ListViews
have const size.
So my question is: how to eliminate these calls? Of course I want to leave proper calls alone (caused by adding items to Adapter and notifyDataSetChanged() ).
I've tried almost anything, but either the whole list doesn't draw itself (when I overriden it's onMeasure() and forced to returned const size without calling super.onMeasure()) or stops updating at some time.
How you implemented the getView() method? If you implement it in the correct way there should be nearly no lagging.
Check out this really really good video:
http://www.youtube.com/watch?v=wDBM6wVEO70
Slides: http://dl.google.com/googleio/2010/android-world-of-listview-android.pdf
As Romain said, work with it not against it. Best is to leave measure() alone and focus on your adapter.
Thats how ListView is implemented.. I don't think that will cause a performance Overhead.. Provided you do things properly there..
For example..
Don't instanciate LayoutInflator inside GetView Method, Do it at class level..
And Inflate View Only if the convertView==null or else just return convertView.. Inflating view is a costly process....
Well like you said these calls are due to measure() and onMeasure() calls of ListViews parents and I'm sure you are using height=wrap_content also with wrap_content on height your ListView will check without stop if your height has changed.
So the solution is to put the height=fill_parent.
I hope this helped you.
The underlying reason for this is that ListView.onMeasure() calls AbsListView.obtainView(), which will request a view from your list adapter. So if your view is being remeasured through animations, your performance will be very poor.