Track and squash allocations. The more you allocate, the more often the garbage collector will need to run, stopping your process from doing anything else for relatively long periods of time, such as 100ms or so.
The best tool I know for this is the Allocation Tracker included in DDMS.
Not only GC can have an impact on the user experience, but superfluous allocations and GC do consume some computing resources.
Here's an example and a small trick. In my app, I have a clock which shows the current (audio) time, including tenth of seconds. This is updated often. And TextView performs allocations internally whenever you call setText() with a CharSequence. But it doesn't allocate anything with the setText(char[] text, int start, int len) variant. This isn't documented, and no one answered when I asked about it.
There are many ones like this. And this is one of the reasons why my app contains 50% native code (but there are other reasons).
Apart from this, I can recommend that you experiment with ProGuard. It performs several optimization passes, and logs such informations as unused methods within the project, which can help you removing leftovers in your code.