Office Hours — Today, October 18

Yesterday, October 17

Oct 18
3:55 PM
Mark M.
has entered the room
Mark M.
turned on guest access
4:00 PM
EGHDK
has entered the room
Mark M.
hello, EGHDK
how can I help you today?
EGHDK
Hey Mark, so I have gotten pretty far with the chat bubble.
It works really really well. There are two things I'm still having trouble with. I'm not sure if you can help but I'll give it a go.
So, my chat bubble is a path with 7 points. I want to round only 4 points out of the 7. How would I go about that?
Mark M.
um, what's a "point"?
EGHDK
I know I can do `paint.setPathEffect(new CorenerPath...` but that rounds all of the points.
Mark M.
I have never used the Canvas API
at least, for anything other than blitting a bitmap onto the screen
certainly none of the line or text drawing APIs
EGHDK
Hrm... alright.
Second is... I want to make sure I'm drawing efficiently. Like... my code works... but I don't know if it's "right". Ya know?
Mark M.
Use Traceview to determine how much time you are spending
4:05 PM
Mark M.
if your onDraw() implementation is a couple of hundred microseconds per invocation, you'll probably be fine, unless you were planning on lots of chat bubbles
EGHDK
Possibly.
Here's a pastebin. I was just wondering if you could take a look to see if there is any big rules I'm breaking. http://pastebin.com/itXy85pq
Mark M.
cache your Paint object
you should be able to initialize that in the constructor
rather than creating new Paint objects every onDraw() call
you may be able to cache your Path object too, clearing out the old data and reusing the instance rather than creating new instances on each onDraw() call
4:10 PM
Mark M.
basically, try to avoid memory allocations where you can, since onDraw() gets called a fair bit
EGHDK
Okay, so try not to put object creation in onDraw()?
Mark M.
(BTW, reset() on Path seems to clear its contents, if I am reading the docs correcty)
er, correctly
where possible, yes, avoid object creation in onDraw()
so, for example, I'd also see if you can get rid of the Point stuff
go with int x[] and int y[] to avoid those allocations
EGHDK
How would you draw without points?
Mark M.
you're not using the Points
more specifically, you are not passing the Points to anyone
they are purely your own bookkeeping with the method
and you are only using them for tracking X's and Y's
which you can track via two int arrays, instead of an array of Point objects
EGHDK
Okay, so two seperate int array would be smaller in size than point objects?
Mark M.
more to the point (pun lightly intended), you avoid creating extra garbage
particularly since your arrays can be precomputed in onSizeChanged(), as they depend only upon your width and height
4:15 PM
EGHDK
How do you know that a Point object is more garbage than an array?
Mark M.
first, you are comparing apples and oranges
you do not have one Point
you have an array of Points
hence, the proper comparison is between an array of Points and two arrays of int
and from a memory consumption standpoint, it's a wash
however, an int is not an object, and therefore has no constructor
by making your arrays be data members, and setting their contents in onSizeChanged(), you generate no new garbage on each onSizeChanged() or each onDraw()
your current implementation creates a seven-element Point array, creates seven Point objects, and tosses it all in the garbage at the end of onDraw()
so that's seven constructor calls and eight total allocations per onDraw()
EGHDK
Interesting take on that. I haven't thought of it in that way before. Thanks Mark.
4:20 PM
EGHDK
I did pick up that head first into Java book. It's pretty good.
About 15% of the way through. Learned a lot of stuff that I knew already, but learned more about some basics like heap and GC.
4:25 PM
Mark M.
yup, a firm grounding in Java will go a long way towards making Android app development a bit less painful
EGHDK
Yep, learning the basics of Java programs is pretty funny.
I now finally know why (String[] args) is there for main. To pass a parameter for a cmd line java program. Never would've guessed it.
Mark M.
if you have another question, go right ahead
EGHDK
Since I'm here, I guess I'll ask as I just asked at #android-dev, but wasn't fulfilled with the answer. What is a leak/memory leak? Why is it bad.
Mark M.
you learned what the heap is in the book, right?
("the book" being _Head First Java_)
4:30 PM
EGHDK
Yep!
Mark M.
the heap space available to a Java program is limited
EGHDK
Especially in Android right?
Mark M.
correct
a memory leak, in a garbage-collected language like Java, is when you have an object that you are no longer using, but cannot be garbage collected
that object's memory is tied up and cannot be reused
this basically subtracts that object's memory out of your available heap space
EGHDK
Oh no! That's not good. It'll keep building up till it's killed by the OS.
Mark M.
correct, or you may get an OutOfMemoryError
OutOfMemoryError, in Android, occurs when you try to create a new object (or array of primitives) and there is insufficient memory for your request
there are two main culprits for this
1. memory leaks, tying up heap space
2. memory fragmentation
remember how I suggested that you avoid creating all those Point objects earlier in this chat?
EGHDK
Yeah
Mark M.
part of the reason for that was speed, to avoid extra constructors and extra CPU time doing garbage collection
part of the reason was to cut down on memory fragmentation
in the beginning, when your process starts up, you have one huuuuuuuuuuuuuge block of memory that is your heap
as you start creating objects (and arrays of primitives), you consume that heap
but, as you let go of those objects, they can be garbage-collected, returning their memory to the heap... sorta
4:35 PM
Mark M.
the "sorta" is that you no longer necessarily have the one huuuuuuuuuuuuuuuuuge block of memory anymore
you have lots of smaller blocks
normally, this is not a problem, as the objects we create tend to themselves be fairly small
EGHDK
Oh... so garbage collection causes the fragmentation?
Mark M.
however, bitmaps become an issue
allocation causes the fragmentation
garbage collection *in Android* does not completely clear up the fragmentation
(garbage collection in standard Java does clear up the fragmentation, through what is known as a "compacting garbage collector", that Android lacks)
bitmaps, under the covers, are large byte arrays (byte[])
and therefore they represent decent-sized chunks of heap space individually
EGHDK
Gotcha.
Mark M.
*if* your heap becomes sufficiently fragmented, you can get an OutOfMemoryError when trying to create a bitmap (e.g., load a PNG off of disk), not because you are truly out of heap space, but that there is no contiguous block of heap big enough for the byte array
EGHDK
OH man. That makes sense.
So how do you fix that?
Mark M.
the fewer objects you create in frequently-called methods (like onDraw() of a View), the less you contribute towards this fragmentation
also, there are special tricks for working with bitmaps that can reduce this problem, such as maintaining your own pool of byte arrays for reuse
4:40 PM
Mark M.
it's the sort of thing that, if you know that you are writing an app that will be prone to this sort of problem (e.g., photo album), you tend to try to deal with it up front
for more general-purpose apps, you tend to not worry about memory fragmentation a ton, in hopes that it never proves to be an issue
EGHDK
Yeah. That clears a lot of things up. So, memory leaks and memory fragmentation. How do I fix memory leaks?
Should I always null out an object when I'm done with it?
Mark M.
no, that is not necessary
Step #1: be very careful when declaring static data members
they represent intentional leaks, as it were
EGHDK
I do that a lot... that means that they're stuck in memory forever?
Oh man. I do do that a lot.
Mark M.
where "forever" = "until the process is terminated", yes
EGHDK
But something like Toast.LENGTH_LONG is a static data member?
Mark M.
yes, but that's a constant
specifically an int
it leaks 4 bytes
not a big deal
static final String KEY_THINGY="foo"; leaks 6 bytes
so don't worry about static final primitives and strings
EGHDK
True. Okay, so what about when an activity finishes. Does all of that stuff get put up for garbage collection?
Mark M.
it depends on the "that stuff"
anything not referenced by a static data member will eventually get garbage collected
4:45 PM
Mark M.
so, usually, your widgets and OnClickListeners and such will all get garbage collected once the activity is destroyed
EGHDK
Wouldn't it be smart to force garbage collection sometimes?
Mark M.
that's usually not necessary and is rarely helpful
bear in mind that Android uses an incremental garbage collector specifically to reduce load on the CPU
it will catch up in time
but do worry about static Customer heyIWantToBeAbleToGetAtThisFromAnywhere=new Customer();
(for any arbitrary Java class like Customer)
if Customer can point to lots of stuff -- like, say, other Customers -- that could wind up being a big memory leak
there's a chapter in my book on using the Memory Analysis Tool (MAT) to help diagnose these sorts of leaks
EGHDK
Yeah, that makes sense. Or if you have a bitmap that's a static. As well.
Okay, I think I will have to read up on that. It's a pretty interesting topic. I just want to make sure I'm getting rid of my objects properly.
Mark M.
or a static cache of bitmaps, to save you reloading them from disk or the network
EGHDK
But I won't go around and start "nulling" everything.
Mark M.
every now and then you will see a code sample that shows setting a variable or something explicitly to null
admittedly, that may slightly increase the speed at which that object can get garbage collected
it's the sort of thing where, if you see Google do it, it's probably a good idea
but if you see J. Random Blogger do it, take that part of the advice with a grain of salt
EGHDK
Duly noted.
4:50 PM
EGHDK
So let's say I have a bitmap static variable, but now I know 100% I don't need it. How would I get rid of it, so I can get that heap back?
Mark M.
*that's* when you set things to null
so if you have static Bitmap avatar; somewhere
where at some point you assign a Bitmap to avatar
that Bitmap is intentionally leaked
to de-leak it, and let it be garbage collected, set avatar to null
my point about not setting things to null was more for garden-variety stuff, like local variables in a method
EGHDK
Yeah. Okay, this is starting to make more and more sense now.
Mark M.
particularly for things like bitmaps, generally try to use some tested library that will handle the caching for you
e.g., Picasso, as covered in the Internet chapter of my book
EGHDK
I didn't know that a heap gets fragmented. That's important to know.
Yeah, JakeWharton was talking to me about mem leaks.
Mark M.
Jake at least had a hand in Picasso, and perhaps wrote it completely
EGHDK
Becuase he said that it works in between activities, which is why you would never want a StrongReference.
Because he said a view with a strong reference will keep the entire activity lingering around.
Mark M.
correct
EGHDK
Someone was complaining about WeakReference.
Mark M.
there are ways in the Java language to "conditionally" hold onto objects
4:55 PM
Mark M.
WeakReference and SoftReference are the two common ones
they tend to be used for cache implementations
EGHDK
Yeah, I haven't really ever seen them used. I saw something similar with Obj C in iOS.
Mark M.
if there are no references to an object, other than by WeakReference or SoftReference, the object can be garbage-collected
EGHDK
Wait... can you rephrase that?
Mark M.
let's suppose we have a Bitmap
we loaded that Bitmap off of disk via BitmapFactory
EGHDK
Yep
Mark M.
in our load-the-Bitmap method, we put it into an ImageView
now the ImageView has a reference to the Bitmap, so the Bitmap cannot be garbage-collected until the ImageView is
that's a strong reference
however, loading bitmaps off of disk is a relatively expensive operation, in terms of disk I/O and CPU time
and we might need that Bitmap again in the future
we could have a HashMap<String, Bitmap> as a static data member somewhere, and put the Bitmap in there, keyed by its path
that way, in the future, we could try to retrieve the Bitmap from the HashMap, and reuse it if we find it
if it is not in the HashMap, we have not referenced this Bitmap before, so we load it from disk
however, a HashMap also is a strong reference
so as we keep adding Bitmaps to the HashMap, our memory leak grows and grows
until eventually we get in trouble
EGHDK
Hmm... alright. Any other specific memory sections in your book?
5:00 PM
Mark M.
there are two main solutions to this problem: limit how many things you put in the HashMap, or use weak or soft references
there's a couple chapters on memory management, including that MAT chapter
EGHDK
View paste
Awesome.
I'm gonna take a look at MAT. I just want to know whether or not I'm getting into trouble.
Mark M.
pages 2249 through 2274 in the book (Version 5.2)
and that's a wrap for today's chat
the transcript will be posted to http://commonsware.com/office-hours/ shortly
no chats next week due to travel
next one is 10am Eastern on October 29th
EGHDK
Thanks
Mark M.
have a pleasant day!
EGHDK
You too.
EGHDK
has left the room
Mark M.
turned off guest access

Yesterday, October 17

 

Office Hours

People in this transcript

  • EGHDK
  • Mark Murphy