This article just bailed me out, with a brief explanation and an overview of what I was trying to do here. Just noting for future reference.
Android Things To Remember
1. The onDetachFromWindow method is your friend, especially when writing image-intensive custom views.
2. Always recycle your Bitmaps.
3. The VM is out to kill you; don’t always trust it.
4. Related to 3, the VM is out to kill you because the relationship between activities, intents, views and other objects can easily create a circular link consuming huge memory resources that are held by some random and unforeseen global object. It’s why singletons are your best friend and your worst enemy.
5. I’d rather be writing iOS apps.
Drawing scaled images in Android is expensive.
So I wrote a custom view which displays a list of bitmaps. The way this works is to draw a grid of images by loading them from disk, then drawing those images using Canvas.drawBitmap(Bitmap, Rect, Rect, Paint).
And during scrolling it was dog slow.
So what I did was to pre-scale the images in a weak hash map:
private WeakHashMap fScaledBitmaps = new WeakHashMap();
private Bitmap getScaledBitmap(String url, int cellWidth, int cellHeight)
{
/*
* Check our cache and return if it's present
*/
Bitmap bmap = fScaledBitmaps.get(url);
if (bmap != null) {
if ((bmap.getWidth() == cellWidth) && (bmap.getHeight() == cellHeight)) return bmap;
// size different; kill bitmap
bmap.recycle();
fScaledBitmaps.remove(url);
}
bmap = ... get our image from interior cache ...
if (bmap == null) {
// bitmap not present; return null
return null;
} else {
// Bitmap loaded. Now grab the scaled version
Bitmap scale = Bitmap.createScaledBitmap(bmap, cellWidth, cellHeight, true);
bmap.recycle();
fScaledBitmaps.put(url, scale);
return scale;
}
}
And this sped up scrolling from sluggish drawing once a second to quick and smooth.
Lesson: drawing a scaled image to a canvas is frighteningly expensive. Like an order of magnitude slower than pre-scaling the bitmap and storing it in a weak reference or weak hash map.
Things to Remember: Why cells with an inserted image are taller than the image in GWT
So here’s a mystery.
Suppose you create in GWT a vertical panel or a flex table, and you add an image which is less than 15 pixels tall:
VerticalPanel panel;
...
panel.add(new Image("images/mydot.png"));
But for whatever reason, the cell displays as 15 pixels tall.
Apparently what happens is that the way the image object is inserted into the
And that blank has vertical height.
If you write the following, you can limit the vertical spacing, allowing for tighter heights:
Image image = new Image("images/mydot.png");
panel.add(image);
DOM.setStyleAttribute(image.getParent().getElement(),"fontSize","1px");
In testing this seems to tighten things up quite a bit.
I need to investigate this further. But apparently when DOM objects are being inserted during the construction of GWT objects, unwanted extra junk (in the form of blank text spaces) is being inserted at the same time.
Things To Remember: GWT Drag and Drop Edition
So I wrote the following code and wired it into the mouse up, down and move listeners so I can do drag and drop:
@Override
public void onMouseUp(MouseUpEvent event)
{
isDragging = false;
// Do something to indicate we're done dragging
DOM.releaseCapture(fClickLayer.getElement());
}
@Override
public void onMouseMove(MouseMoveEvent event)
{
if (isDragging) {
// Do something with the event to drag
}
}
@Override
public void onMouseDown(MouseDownEvent event)
{
DOM.setCapture(fClickLayer.getElement());
// Note the initial state to start dragging
}
And of course after the first three move events I stopped receiving move events, but instead the widget would be selected.
After banging my head against a brick wall for a couple of hours I realized I needed to prevent the browser from taking the default behavior on the received click and move events. And that’s done with the preventDefault() method:
@Override
public void onMouseUp(MouseUpEvent event)
{
isDragging = false;
// Do something to indicate we're done dragging
DOM.releaseCapture(fClickLayer.getElement());
}
@Override
public void onMouseMove(MouseMoveEvent event)
{
if (isDragging) {
event.preventDefault(); // ADD ME HERE
// Do something with the event to drag
}
}
@Override
public void onMouseDown(MouseDownEvent event)
{
DOM.setCapture(fClickLayer.getElement());
event.preventDefault(); // ADD ME HERE
// Note the initial state to start dragging
}
Duh.

As an aside, here’s a snippet of code that you can use to prevent something from being selected in HTML. You can also do this in CSS, I suppose. I encountered this snippet of code here.
private native static void disableSelectInternal(Element e, boolean disable)
/*-{
if (disable) {
e.ondrag = function () { return false; };
e.onselectstart = function () { return false; };
e.style.MozUserSelect="none"
} else {
e.ondrag = null;
e.onselectstart = null;
e.style.MozUserSelect="text"
}
}-*/;
I first tried hooking this up to the class receiving the mouse events, but to no avail.
UI Performance
I just spent the weekend rewriting an Android application for performance.
When I first start learning a UI framework, be it for iOS, Android, Java Swing, GWT, MacOS, Windows, or X, the two questions I first want to answer are:
- How do I build a custom view?
and
- How do I build a custom view container and perform custom layout of the children within that container?
With those two bits of information you can rule the world. (Or at least the framework.)
The problem with most applications running like a dog, especially on mobile devices, is that most frameworks are inefficient at maintaining more than a couple of dozen views within a window. This isn’t a problem when you’re talking about putting up a dialog with a bunch of controls or have a relatively static display. But when you start talking about dragging and dropping objects, or when you are talking about scrolling items in a scroll view, things can go to hell very quickly.
To take a concrete example, I put together a view which contains a scrolling area, and inside the area each item in the list of items is represented by an image, a couple of buttons and a label of text. The natural way in Android to do this is to build a ListView, create a ListAdapter and in response to each request for a view, use a LayoutInflater (as needed) to construct a view hierarchy that contains a layout or three, representing the buttons as views, the image as a view, and the text as a view, all layered on other views. On the iPhone it’s the same story; a UITableViewCell can contain a hierarchy of other views which represent the contents of the cell.
For a list of 20 items, this translates into over a hundred-something views, minimum.
And on both Android and iOS, dragging around all that crap takes forever.
My solution in each of these cases is to reduce the complexity. On the iPhone override the UITableViewCell as a single custom view which draws the buttons, widgets and components in the -drawView() method. That way, on the screen you have 7 views, not over a hundred.
On Android the solution was even more radical: instead of a list view, I just used a ScrollView and created a custom view which draws the entire list. Use the Canvas’ getClipBounds() method in the canvas passed into onDraw() to determine what needs to be drawn, and draw it all in one view.
With this technique you eliminate manipulating a hundred views, and can easily make something go from impossibly jerky to smooth as silk, even on slower devices.
On Memory Leaks in Java and in Android.
Just because it’s a garbage collected language doesn’t mean you can’t leak memory or run out of it. Especially on Android where you get so little to begin with.
Now of course sometimes the answer is that you just need more memory. If your program is a Java command line program to load the entire road map of the United States to do some network algorithms, you probably need more than the default JVM configurations give you.
Sometimes it’s not even a full-on leak, but a large chunk of memory isn’t being released in time as a consequence of some holder object that isn’t being released in time.
There are some tools that can help. With Android, you can use DDMS to get an idea what’s going on, and you can even dump a snapshot of the heap by using the Dump HPROF File option. (You can also programmatically capture uncaught exceptions on startup of your application or activity and dump an hprof file within the exception handler like so:
public void onCreate(Bundle savedInstanceState)
{
...
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()
{
@Override
public void uncaughtException(Thread thread, Throwable ex)
{
try {
File f = new File(Environment.getExternalStorageDirectory(),"error.hprof");
String path = f.getAbsolutePath();
Debug.dumpHprofData(path);
Log.d("error", "HREF dumped to " + path);
}
catch (IOException e) {
Log.d("error","Huh?",e);
}
}
});
...
}
Of course once you have an .hprof file from Android you have to convert it to something that can be used by an application such as the Eclipse Memory Analyzer tool using the hprof-conv command line application included as part of the Android SDK; there is more information on how to do this and how to use the MAT tool here: Attacking memory problems on Android.

One place where I’ve been running into issues is with a clever little bit of code which loads images from a separate thread from a remote resource, and puts them into a custom view that replaces the ImageView class. This little bit of code creates a background thread which is used to talk to a remote server to download images; once the image is loaded, a callback causes the custom view to redraw itself with the correct contents. A snippet of that code is below:
/* Cache.java
*
* Created on May 15, 2011 by William Edward Woody
*/
package com.chaosinmotion.android.utils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map.Entry;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
public class Cache
{
/**
* Our callback interface
*/
public interface Callback
{
void loaded(String url, Bitmap bitmap);
void failure(String url, Throwable th);
}
/**
* Item in the queue which is waiting to be processed by our network thread(s)
*/
private static class QueueItem
{
String url;
Callback callback;
QueueItem(String u, Callback c)
{
url = u;
callback = c;
}
}
/// The handler to thread to the UI thread
private Handler fHandler;
/// The event queue
private LinkedList<QueueItem> fQueue;
/// The global cache object, which will be created by the class loader on load.
/// Because this is normally called from our UI objects, this means our Handler
/// will be created on our UI thread
public static Cache gCache = new Cache();
/**
* Internal runnable for our background loader thread
*/
private class NetworkThread implements Runnable
{
public void run()
{
// Start HTTP Client
HttpClient httpClient = new DefaultHttpClient();
for (;;) {
/*
* Dequeue next request
*/
QueueItem q;
synchronized(fQueue) {
while (fQueue.isEmpty()) {
try {
fQueue.wait();
}
catch (InterruptedException e) {
}
break;
}
/*
* Get the next item
*/
q = fQueue.removeLast();
}
/*
* Read the network
*/
try {
/*
* Set up the request and get the response
*/
HttpGet get = new HttpGet(q.url);
HttpResponse response = httpClient.execute(get);
HttpEntity entity = response.getEntity();
/*
* Get the bitmap from the URL response
*/
InputStream is = entity.getContent();
final Bitmap bmap = BitmapFactory.decodeStream(is);
is.close();
entity.consumeContent();
/*
* Send notification indicating we loaded the image on the
* main UI thread
*/
final QueueItem qq = q;
fHandler.post(new Runnable() {
public void run()
{
qq.callback.loaded(qq.url,bmap);
}
});
}
catch (final Throwable ex) {
final QueueItem qq = q;
fHandler.post(new Runnable() {
public void run()
{
qq.callback.failure(qq.url,ex);
}
});
}
}
// httpClient.getConnectionManager().shutdown();
}
}
/**
* Start up this object
*/
private Cache()
{
fHandler = new Handler();
fQueue = new LinkedList();
Thread th = new Thread(new NetworkThread());
th.setDaemon(true);
th.start();
}
/**
* Get the singleton cache object
*/
public static Cache get()
{
return gCache;
}
/**
* Get the image from the remote service. This will call the callback once the
* image has been loaded
* @param url
* @param callback
*/
public void getImage(String url, Callback callback)
{
synchronized(fQueue) {
fQueue.addFirst(new QueueItem(url,callback));
fQueue.notify();
}
}
}
Now what this does is rather simple: we have a queue of items which are put into a linked list, and our background thread loads those items, one at a time. Once the item is loaded, we call our callback so the image can then be handled by whatever is using the service to load images from a network connection.
Of course we can make this far more sophisticated; we can save the loaded files to a cache, we can collapse multiple requests for the same image so we don’t try to load it repeatedly. We can also make the management of the threads more sophisticated by creating a thread group of multiple threads all handling network loading.
We can then use this with a custom view class to draw the image, drawing a temporary image showing the real image hasn’t been loaded yet:
/* RemoteImageView.java
*
* Created on May 15, 2011 by William Edward Woody
*/
package com.chaosinmotion.android.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
public class RemoteImageView extends View
{
private Paint fPaint;
private Bitmap fBitmap;
private String fURL;
public RemoteImageView(Context context)
{
super(context);
// TODO Auto-generated constructor stub
}
public void setImageURL(String url)
{
fBitmap = null;
fURL = url;
Cache.get().getImage(fURL, new Cache.Callback() {
public void loaded(String url, Bitmap bitmap)
{
fBitmap = bitmap;
invalidate();
}
public void failure(String url, Throwable th)
{
// Ignoring for now. Could display broken link image
}
});
}
@Override
protected void onDraw(Canvas canvas)
{
if (fPaint == null) fPaint = new Paint();
canvas.drawColor(Color.BLACK);
if (fBitmap == null) return; // could display "not loaded" image
canvas.drawBitmap(fBitmap, 0, 0, fPaint);
}
}
This is a very simple example of our using the Cache object to load images from a background thread. We can make this far more sophisticated; we can (for example) display a “loading” image and a “image link broken” image. We can also alter the reported size during onMeasure to return the size of the bitmap, or we can center the displayed bitmap or scale the bitmap to fit. But at it’s core, we have a simple mechanism for displaying the loaded image in our system.

Can you spot the leak?
I didn’t, at first.
Here’s a hint: Avoiding Memory Leaks
Here’s another: the RemoteImageView, being a child of the View class, holds a reference to it’s parent, and up the line until we get to the top level activity, which holds a reference to–well–just about everything.

No?
Okay, here goes.
So when we call:
Cache.get().getImage(fURL, new Cache.Callback() { ... });
The anonymous inner class we create when we create our callback holds a reference to the RemoteImageView. And that inner class doesn’t go away until after the image is loaded. So if we have a few dozen of these and a very slow connection, the user switches from one activity to another–and we can’t let the activity go, because we’re still waiting for the images to load and be copied into the image view.
So while it’s not exactly a memory leak, the class can’t be let go of, nor can all the associated resources, until our connection completes or times out. In theory it’s not a leak, exactly, because eventually the memory will be released–but it won’t be released soon enough for our purposes. And so we crash.

So how do we fix this?
Well, we need to add two things. First, we need to somehow disassociate our view from the anonymous inner class so that, when our view no longer exists, the callback class no longer holds a reference to the view. That way, the activity can be reclaimed by the garbage collector even though our callback continues to exist. Second, we can remove the unprocessed callbacks so they don’t make a network call to load an image that is no longer needed.
To do the first, we change our anonymous inner class to a static class (that way it doesn’t hold a virtual reference to ‘this’), and explicitly pass a pointer to our outer class to it, one that can then be removed:
/* RemoteImageView.java
*
* Created on May 15, 2011 by William Edward Woody
*/
package com.chaosinmotion.android.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
public class RemoteImageView extends View
{
private Paint fPaint;
private Bitmap fBitmap;
private String fURL;
private OurCallback fCallback;
public RemoteImageView(Context context)
{
super(context);
// TODO Auto-generated constructor stub
}
private static class OurCallback implements Cache.Callback
{
private RemoteImageView pThis;
OurCallback(RemoteImageView r)
{
pThis = r;
}
public void loaded(String url, Bitmap bitmap)
{
if (pThis != null) {
pThis.fBitmap = bitmap;
pThis.invalidate();
pThis.fCallback = null; // our callback ended; remove reference
}
}
public void failure(String url, Throwable th)
{
// Ignoring for now. Could display broken link image
if (pThis != null) {
pThis.fCallback = null; // our callback ended; remove reference
}
}
}
public void setImageURL(String url)
{
fBitmap = null;
fURL = url;
fCallback = new OurCallback(this);
Cache.get().getImage(fURL, fCallback);
}
@Override
protected void onDraw(Canvas canvas)
{
if (fPaint == null) fPaint = new Paint();
canvas.drawColor(Color.BLACK);
if (fBitmap == null) return; // could display "not loaded" image
canvas.drawBitmap(fBitmap, 0, 0, fPaint);
}
@Override
protected void onDetachedFromWindow()
{
// Detach us from our callback
if (fCallback != null) fCallback.pThis = null;
super.onDetachedFromWindow();
}
}
The two biggest changes is to create a new static OurCallback class which holds a reference to the view being acted on. We then hold a reference to the callback that is zeroed out when the callback completes, either on failure or on success. Then on the onDetachedFromWindow callback, if we have a request outstanding (because fCallback is not null), we detach the view from the callback. Note that because all the calls in the callback are done on the UI thread we don’t need to synchronize access.
This will now detach the view from the callback when the view goes away, so the activity that contains the view can be reclaimed by the memory manager.
Our second change is to remove the request from the queue, so we don’t use unnecessary resources. While not strictly necessary for memory management purposes, it helps our network performance. The change here is to explicitly remove our callback from the queue.
First, we change our onDetachedFromWindow() call to remove us (by callback) from the cache:
@Override
protected void onDetachedFromWindow()
{
// Detach us from our callback
if (fCallback != null) {
fCallback.pThis = null;
Cache.get().removeCallback(fCallback);
}
super.onDetachedFromWindow();
}
Second, we add a method to the cache to look for all instances of requests with the same callback, and delete the request from the queue. If it isn’t in the queue, it’s probably because the request is now being acted upon by our networking thread. (If we were particularly clever we could signal our networking thread to stop the network request, but I’m not going to do that here.)
So our method added to the Cache is:
/**
* Remove from the queue all requests with the specified callback. Done when the
* result is no longer needed because the view is going away.
* @param callback
*/
public void removeCallback(Callback callback)
{
synchronized(fQueue) {
Iterator iter = fQueue.iterator();
while (iter.hasNext()) {
QueueItem i = iter.next();
if (i.callback == callback) {
iter.remove();
}
}
}
}
This iterates through the queue, removing entries that match the callback.

I’ve noted this on my list of things not to forget because this (and variations of this) comes up, with holding references to Android View objects in a thread that can survive the destruction of an activity.
The basic model is when the view goes away (which we can detect with a callback to onDetachedFromWindow), to disassociate the callback from the view and (preferably) to kill the background thread so the view object (and the activity associated with that view) can be garbage collected in a timely fashion.
Snippets of GWT
Strategy for validating text input in a TextBox during input:
One way to validate that the string being entered into a text box is properly formatted is to reject key changes as the user types, if the resulting string would result in an invalid string. The strategy I’m employing is to add a key press handler and schedule a deferred command: the deferred command then reverts the contents of the text box if the contents are illegal.
Thus:
public class TestEditorBox extends TextBox
{
public TestEditorBox()
{
super();
/*
* Hang handler off key press; process and revert text of it doesn't
* look right
*/
addKeyPressHandler(new KeyPressHandler() {
@Override
public void onKeyPress(KeyPressEvent event)
{
final String oldValue = getText();
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
@Override
public void execute()
{
String curVal = getText();
if (!validate(curVal)) setText(oldValue);
}
});
}
});
}
private boolean validate(String value)
{
// return true if the string is valid, false if not.
}
...
}
The things in Android that keeps tripping me up.
android:layout_weight
When building a layout, the biggest thing that keeps going through my mind is “how do I get this object to lay itself out so it consumes only what is left in a linear layout flow?”
And the answer to that is android:layout_weight.
If you specify a layout and you want one of the controls to land at the bottom of the screen with a fixed height, then the other control in the LinearLayout should be set with height “match_parent”, and weight set to 1. This causes it to consume the rest of the space. (Bonus: you can split the view by having multiple controls with different weights, and you can even achieve an effect such as one control taking a third and the other two thirds, by using appropriate weights.)
android:gravity
It’s the other one I keep forgetting about. It allows you to center something on the screen, or flush it to the right, or whatever. Apply to the view to control it’s positioning inside the container parent.

I also have some code lying around here which helps to control multiple activities where a single activity would normally live, that I cobbled together by reading this post; he goes into how to extend an ActivityGroup to achieve multiple activities within the same tab group item. I think this principle can be extended to support other interesting effects, such as having a list view where each row in the list is it’s own activity. But that’s something I need to plug away at to see if I can make it work.
It’s not quite black magic…
Problem: I need to connect to an SSL socket while ignoring the trust certificate chain, so I can connect to a self-signed SSL connection. In particular I want to connect to an LDAP server using the Netscape LDAP library but I keep hitting the error:
“Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target”
I managed to find a snippet of code with the correct solution here, and am basically repeating it here for my own edification.
First, to create a client socket you need to use a socket factory. But in order to connect to an SSL socket while bypassing the trust chain on the certificate, you must first set up the socket factory:
SocketFactory gSocketFactory;
...
SSLContext sc = SSLContext.getInstance("SSL");
TrustManager[] trustAll = new TrustManager[] {
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] arg0,
String arg1) throws CertificateException
{
}
@Override
public void checkServerTrusted(X509Certificate[] arg0,
String arg1) throws CertificateException
{
}
@Override
public X509Certificate[] getAcceptedIssuers()
{
return null;
}
}
};
sc.init(null, trustAll, new SecureRandom());
gSocketFactory = sc.getSocketFactory();
Once the socket factory has been created, you can make an SSL connection:
Socket socket = gSocketFactory.createSocket(); socket.connect(new InetSocketAddress(host,port)); // Do stuff with the socket
The magic bit of code creates a new trust management chain and installs it into a new SSLContext object, used to build our socket factory. The trusted chain contains one X509TrustManager, which does–nothing. And thus, we can connect to all SSL sockets without worrying if we have the correct certificate installed or if the remote SSL connection is properly signed.
Usual caviats remain: don’t do this unless you must, it creates all sorts of security problems (such as increased susceptibility to man in the middle attacks), your mileage may vary, limited supplies are available, no shoes no shirt no service.