0

Okay, so I after playing around with the Android SDK a little I have decided to develop a full application. Not necessarily to release on the store (I don't really have the tools at my disposal to do proper QA and so wouldn't feel right; I could only test on my one personal device) it is mostly just a personal project for fun and learning. In the end, I decided on a camera application because I use my camera fairly often so it is the kind of application I would end up actually using if I made it and also because I am quite excited by the features of the new Camera2 API in Android L and want to give them a try.

Anyway, I have been thinking on the design/architecture of the application for a while and I have come across a potential problem that I cannot really resolve myself as I am not only not really familiar with GUI programming of this nature but also not 100% on Java and the Android SDK. They both sit well outside the purview of my dayjob.

Now I know enough that I really need to keep my UI thread separate from everything else, but what I am unsure about is first of all, what I should devote extra threads to (I was thinking one to handle image capture and storage, and another to handle the settings? perhaps that is over doing it) and also whether to have background threads which the UI thread communicates with through Events or simply to spawn threads as and when they are needed. Perhaps a single intermediate background thread which arbitrates between the UI thread and any background processing that needs to be done? What I mean to ask is, how do I decide these things? Are there general/best practices?

I'm really asking because I want to get this done properly and plan out the application thoroughly beforehand since in the past I have found that if I just dive right in I get confused very easily and end up losing faith and dropping the project. I hope somebody can help. It's not a question that I have found easy to phrase in such a way that Google would provide satisfactory results.

Luke
  • 2,434
  • 9
  • 39
  • 64

3 Answers3

2

I think you might consider thinking about it this way:

The UI thread is where most stuff runs. It is also, occasionally, called the "main" thread, because it is, uhhh... the main thread.

Unless your program is wildly complex, you probably don't need to worry about an architecture for threads. All you need to worry about is getting slow stuff off the UI thread. That's it. You don't care where they go, just not the UI thread.

If you buy that, there are some nifty choices:

  1. Intent Service: If, a bit metaphorically, the methods you need to run in "background" have void return types, an intent service is the perfect solution. You communicate with it using Intents and, since it has only one thread, tasks you submit to that thread are run in order.
  2. AsyncTask: These are fraught with problems but people get a lot of programming done with them. They run in a pool of around 6 threads, but (surprise!) run in order anyway.
  3. Your own Java Executor: Use this if you need behavior similar an AsyncTask, but with more control.
  4. New thread per task: Just don't do this. Really.

In any of these cases, though, you don't really care on which threads your tasks are running. You make a policy about the number of threads that makes sense on the target device and then run your slow stuff on one of them.

...and "slow" should include all I/O: databases, file system, network, etc., as well as major computation.

G. Blake Meike
  • 6,615
  • 3
  • 24
  • 40
  • AsyncTask's run serially on a single thread in recent versions of Android, unless otherwise specified. – Steve M Aug 15 '14 at 20:42
  • @svenoaks: not true! They run on an Executor with a pool of threads with size around 6. In front of the Executor, however, there is a dequeue that forces in-order execution. – G. Blake Meike Aug 15 '14 at 20:45
  • Oh you're right, even though the documentation spefically says it executes on a single thread (which it appears to from the user's perspective), the source says differently. – Steve M Aug 15 '14 at 21:34
  • Yeah. The problem comes when you have code run from the AsyncTask. That code must be thread-safe, because there is no guarantee that it will always be run on the same thread (as there would be, if it worked as the doc describes) – G. Blake Meike Aug 15 '14 at 22:12
  • You're right. I have been overthinking it I think. I am happy with the other answers though I will accept this since it seems to be most thorough with regards to explaining my options. Thanks! – Luke Aug 15 '14 at 22:14
  • I would add Needle to the list; it's a simple and powerful multithreading library for Android. https://github.com/ZsoltSafrany/needle – Zsolt Safrany Aug 19 '14 at 13:08
1

You want to keep things as simple as possible. You don't need a thread to set settings, and you don't need an intermediary thread. These things are only going to create unnecessary complication. You only need to take long running operations off the UI thread.

Take a look at the structures the Android framework provides to make multi-threading easier first. This will help simplify your application. These would include IntentService and AsyncTask. If those won't meet your needs take a look at the java.util.concurrent package. Using a raw Thread is often not advisable.

Another library that could come in handy is an Event Bus like Otto. This will prevent memory leaks that can occur with using AsyncTask.

Steve M
  • 9,296
  • 11
  • 49
  • 98
  • Thanks, I have been overthinking things... I can tend to do that when I just think and think and never do. Thanks for the links, they should come in handy! – Luke Aug 15 '14 at 22:15
1

You dont need to worry about threads when it comes to image capture. When you want to take a picture you do so by opening the Camera App on the device. Here is a good way of doing that.

Android SDK provides Asynctask which does things for you in the background thread, like a network call and updates the UI once its done.

You can also use an IntentService, which runs even if you exit the app and does things like upload/download without the user having to worry about it. Loaders are useful when the underlying data often changes and you need to update UI quickly (searching contacts in autocomplete text for example).

http://www.vogella.com/tutorials/AndroidBackgroundProcessing/article.html

Refer to this tutorial, its a good start. Hope this helps.

Community
  • 1
  • 1
hrishitiwari
  • 634
  • 7
  • 15
  • Akk! No, no, no! A Service runs on the UI thread! ... and, FWIW, a Loader is an AsyncTask. – G. Blake Meike Aug 15 '14 at 21:08
  • 1
    Well yes, Loaders use AsyncTask internally, but Loaders are better for some cases, its good to know all the options. – hrishitiwari Aug 15 '14 at 21:21
  • A `Service` *normally* runs on the app's main thread, but it can be set up in the manifest to run in its own process, in which case it will have its own main thread. – Kevin Krumwiede Aug 15 '14 at 22:06
  • Thanks for the links, though using the Camera App to take a picture isn't exactly what I was going for. I was hoping to develop my own application using the Camera2 API with a UI of my own design... – Luke Aug 15 '14 at 22:17