问题
Running asynchronous tasks off of the UI thread then modifying the UI is a common issue in android development, so I decided to take some time, research, and play around with different techniques and find what works best for me.
What I considered important factors:
- Should work reliably
- Code readability
Activity
orFragment
should be kept clean of as much of thread management as possible
Here is the summary of my impressions (which may be wrong and some are just opinions) about the various methods:
AsyncTask
I was using simple AsyncTask
without LoaderManager
when I first jumped into Android:
- Had intermittent issues, I wrote my own
AsyncTaskManager
to manage them with the activity life cycle. - There are some limitations to number of tasks and memory leaks have been reported before.
- Biggest issue with these was that they made my code extremely convoluted, and simplifying the code defeated the purpose of using them in the first place.
AsyncTaskLoader with LoaderManager
This seems to be the recommended way to do this, so I researched it a bit:
- After reading about these a bit, it seems the main reason this method is recommended is because it manages the tasks with the
Fragment
life cycle, and from my understanding basically just restarts the tasks if necessary. It doesn't seem to be able to receive the results of a task started before an activity was restarted after the activity restarts. - All the task parameters seem to have to be
Parcelable
orSerialiazable
to go into aBundle
object.
Handler, Threads, with Messages
This is the method I settled on:
- Easy to implement, extremely customizable.
- You get access to the thread executing the task: set priority, set thread name for debugging, set daemon, and etc.
- Seems much more responsive than with using AsyncTasks, based on an eye test where I click a button a lot of times and watch the results and threads flash by ;) I could benchmark this.
- To handle life cycle issues, can write a singleton class that manages messages (persists while the process is alive). Stores them when a given activity's handler is not set up, then forwards them to the activity handler if it asks for its missed messages. Meaning a task doesn't have to restart with the same parameters, which can be critical for tasks that are non-idempotent.
So I came to the conclusion that using Handler
, Threads
, and Messages
is a much better solution, but I'm convinced I'm missing something because nearly everywhere I looked the recommendation was to use the AsyncTaskLoader
method. What am I missing?
Thanks for the input.
回答1:
What you're missing is that classes like AsyncTask
and LoaderManager
were written with Android in mind. Meaning, the OS is designed to make the most of minimal hardware when compared to a desktop computer. AsyncTask
limits your thread pool because you have much stricter thread limitations than on other systems. If you try to spawn 100+ threads, new threads will be rejected or crash the system. You can certainly use Thread
and Handler
, but you're on your own as far as managing it.
Last I heard, AsyncTask
supports 10 threads with a queue depth of 10 tasks (it may have increased in later versions). If this is restrictive, you can always grab the source and write your own. I've done it before. The important thing you want to consider is, can I run into trouble down the road with spawning too many threads, and if so, how am I going to handle it.
To address your question as to why it's recommended to use LoaderManager
and AsyncTaskLoader
, it's just a convenience. It's an easy way to reload data and get it to the parts of your code that depend on that data. It's not warranted in every situation.
回答2:
Handler
, Threads
, and Messages
are low-level classes. This gives you flexibility -- you can combine them as you see fit to solve your particular problem. However, you also need to take care of a lot of low-level stuff as well: stopping/starting threads, routing to the correct thread, saving/restoring or re-creating instance when activities are re-created, etc.
Loaders take care of most of this for you and are designed to solve one particular problem well -- loading data in an activity. The biggest plus is that the Activity
(or FragmentActivity
) will take care of managing and restarting your loaders when the activity is re-created (which is quite tricky to do right without leaking). It also caches data so you don't need to do this yourself. That said, if you want to do something slightly different, using Loaders might get awkward. So if need more flexibility, consider AsyncTask
. If that doesn't fit, go one level lower and use Threads
and Handler
.
来源:https://stackoverflow.com/questions/13117183/why-use-asynctaskloader-with-loadermanager-instead-of-simple-handler