Remember that in the vast world of Android functions there's a whole boatload of operations that only execute on the main thread, system events,input events,application callback, services,and event alarms.And for the most part,any code that you write executes inside one of these operations,which means it also runs on the main thread.
Now,if you recall,work that executes on the main thread gets there after being pulled from the front of a work queue,so blocks of work are done in order,and the next block of work isn't processed until the current one is completed,which means if there is a large chunk of work between an input event and its callback,then the user will have to wait longer than expected to see results.And don't forget that the main thread is also where most of the screen redering occurs.While an animation or screen update is occurring,the system will try to draw the screen every 16 milliseconds or so to achieve smooth 60 frames per second.The problem is that this is happening while the thread is also responding to app input events.So if your app is in the middle of an animation and some randomwork packet takes longer than expected,you'll miss your chance to render that next frame within the 16 millisecond window,and that frame will be delayed.This is what we call a dropped frame,and when this happens,users start to notice.
The direct solution here is to move anything that might upset the 16 millisecond window over somewhere else,like to a different thread.This way it won't be contesting with the UI thread for work to be done,and won't be interrupting the drawing of the screen,which is the whole point of threading on Android in a nutshell.
So the question at hand,what's the best way to offload this work,and how do you choose what types of work to offload?Thankfully,the Android framework has provided a handful of classes to help make this a bit easier for you.For example,the AsyncTask class is ideal for helping you get work on and off the UI thread the right way.HandlerThreads are great when you need a dedicated thread for callbacks to land on.ThreadPools work best when you can break your work up into really small packets,and then toss them to a bunch of threads.IntentServices are really ideal for background tasks or when you need to get intent work off the UI thread.And like everything else,there is not a silver bullet here,but knowing which primitive is best for what situation can save you a lot of headaches.
But note that having all those fancy helper classes doesn't hide the big problem,memory.See,threading and memory have never really played well,and on the Android platform it's no different.For example,if you declare one of those fancy threading primitives inside of an activity,it now contains an implicit reference to the outer activity,which can cause a memory leak if the activity is destroyed,but the threaded work is still alive.Or,what happens when the user rotates the device,destroying an activity that spawned a bunch of threaded work?I mean,chances are that those work packets would have references back to various UI objects that don't really exist anymore.
And the truth is that the Android platform is flooded with threads.If you need a reminder of that,grab a Systrace capture and check out all the cool stuff that's going on underneath the hood that you never really knew about.See,at the end of the day,threading is critical to ensure high performance of your android app,but there's lots of other problems that you hvae to worry about that as well,which is why you should check out the rest of the Android Performance.