Android Untold Stories -- Deep secrets that documentations did not tell you
1. ImageView/ImageButton
When wanting to show graphical buttons, ImageView/ImageButton come to you at a very first glance. It is selector that enables us to implement different states of impressions of the buttons. But be cautious, there is a trap in selector: You must guarantee that the size of images of different states are the same. Otherwise, the images of focused state and pressed state will be scaled to match the size of default image regardless of the scaleType attribute defined in XML.
2. RemoteViews Binder transaction
You'd better not transfer any large objects to RemoteViews, Bitmaps, for instance. Even if you want send Bitmaps to RemoteViews, the size better be not too large. And you cannot send too often, either. Otherwise, Binder will fail to deliver it to RemoteViews, because of Java Binder transaction failure(Out of Memory error, perhaps). What's worse, RemoteViews fail to update because of failed delivery. The specific limits probably be at most 500*300 by size and at most 3 or 4 by at once.
You should keep in mind of this when you are developing Home Widgets especially. If you want to show some images on Home Widgets, you had better make it small enough and you'd better not use more than 3.
3. callbacks onMeasure(), onLayout() and onDraw() of android.view.View
When you implement your own customized view, some callbacks of View are useful and must be overridden. OnDraw() is one of them on which you must put your imaginary drawing. The sizes and measurements of the view you are constructing are important when drawing. The width and height of your view which also define your drawing area are most important, in particularly. You can get width and height of view when drawing in onDraw(), of course. But, sometimes, that is too late when you want to initialize some important conditions which play a very important role in your customized view before you actually do drawing in onDraw(). A possible alternative is to get them in onLayout(), or in onMeasure(), as some so-called experts suggest. But onLayout() is much more intuitive to comprehend than onMeasure(), which is also the reason I prefer it. OnMeasure(), instead, is harder to comprehend and use. And you should know the calling sequence of these callbacks, too: onMeasure() comes first, then is onLayout() followed by onDraw() finally. And, you might know, they get called more than once.
4. invalidate() of android.view.View -- how to do refreshments
For most developers, overriding onDraw() and calling invalidate() are probably one of the most usual way to implement customized views and sophisticated animations. But, as you know, invalidate() costs. One way to optimize it is invalidate only a proportional part instead of the whole drawing area with invalidate(int left, int top, int right, int bottom) which invalidates a rectangle defined by (left, top, right, bottom). This has been proven that is much efficient.
Besides, how to do refresh also need to be taken into account. View provides some methods like postInvalide(), postInvalidateDelayed() and the like. But that is hard to control though they are easy to use. No effective way to stop the loop and it is very easy to make it more frequent by adding another postInvalidate() loop which causes chaos to your drawing. Instead of using View's, you'd better implement your own handler loop to do the refreshments which is much easier to control: you can stop message loop by removing the message from message queue at any time necessary to stop refreshing. And, in the same way, restore refreshment loop by adding a message onto message queue. In addition, another point to note, before add a new message onto message queue, you'd better remove it first in order to ensure the loop goes smoothly at the desired interval you speficied, because at anytime there should be only one message to process in message queue which forms a healthy handler message loop with signle chain(currently let's call that like this).
5. binding with a Service
In the same package(application), if the service lives in the same package, you just do it as normally: write an AIDL and bind to the serivice by specifying their class names.
But, if your target service is outside your package, there are two additional things to note: first, the target service must be visible to others. In other words, the export attribute of that service must be set to true to ensure it is visible by other application and packages. Second, you must write a intent filter for target service to match the intent specified by bindService(). Otherwise, ActivityManager would complain that it cannot find the target service.