I have been working on an Android application that uses Google maps and then runs some lengthy network intensive operations in the background. Currently, I am using a thread to run them on and they take anywhere from 30 seconds to 7 minutes to finish. After watching a few courses on Pluralsight about AsyncTasks and Background services, I now know that threads should ideally not be used for anything taking more than a few seconds. I am now altering my solution to run live with GPS rather than taking several minutes to perform the operations. The goal is to update an array every OnLocationChanged event.
I am having trouble in thinking about how I could alter a global array every OnLocationChanged event while also accessing it from the UI main thread. What is my best option for accomplishing this? Would I be able to use a process or AsynTask to accomplish this or would I need to go client/server route? Where would the OnLocationChanged be called?
First off, onLocationUpdated is called on the UI thread. So you don't have to worry about multithreading there.
Secondly- if you have a variable that needs to be touched by two threads you just use a semaphore and take it before you need to access it on each thread, and release it when done. Make sure to keep that block of code as small and quick as possible. There's more advanced stuff you can do for high performance needs, but that's good enough for 99% of code.
Thirdly- as I mentioned in my comment, your understanding of threading is wrong. The UI thread should not be used for more than is needed. AsyncTasks should not run for more than a few seconds (as there's a single thread they run on by default, so running long would block other requests). But a Thread can run as long as it needs to, and should be used if it needs long term background processing.
Related
I am mostly confused between Services and Coroutines
I don't understand why should i be using coroutines vs when should i be using Services? When i am downloading a file, do i need to use service or can i just use coroutine? Both of them can not survive process death.
And if i can download a file using coroutines, what do i need the service for at all?
Can you please list all of these and give some examples where i would want to use Service, where would i use Coroutines and where would i use WorkManager?
Also, should i be using AsyncTask at all? Because i read that it has many flaws in it and it can create memory leaks.
I also read this article about background work:
https://developer.android.com/guide/background
but it talks about only Workmanager and Coroutines but no mention of services. Why?
Background Work
https://developer.android.com/guide/background
In Android and any UI application, you have the Main Thread. If you do something heavy on the Main Thread you will block the user's interaction. So you need to do such work in another Thread. You can do this on Android using:
You create a Thread
Executor with a pool of Threads
Handler
AsyncTask
RxJava
Coroutines
App lifecycle
https://developer.android.com/guide/components/activities/process-lifecycle
But the Android application lifecycle is a complicated thing. You can't know when an application will die. It is a process that consumes some amount of resources. When the OS has no resources it will kill some applications. So you have priorities and based on them - the application is less likely to be killed. And they are part of the above link. As you can guess - if the app is visible - it is highly unlikely to die. But what if you want to finish your work, but without keeping the user engaged. This is point 3 from the link:
You can use a Service
The idea of the Services is that you can do something "in the background", but it does not mean a background Thread. It means that it is in the background for the user. The plain Services starts on the MainThread. There are specific implementations that has their own Background Thread.
And also what a Service gives you - it will make your application less likely to be killed.
WorkManager
There are many APIs in Android. During the years they become more and more. But at the same time there are more and more restrictions - with the idea that the user's battery must be saved. Also the network resources. So it is hard to pick the right API, but at the same time workaround the restrictions.
So WM was invented. It is for cases where you want your work to finish for sure at some point. Even on a device restart. But you don't care that much about timing. Uploading a video is the best example. If you want something with an exact period like every 1 hour for sure - You need to use AlarmManager. With WM it might be 1 hour, 1 hour and a half, 4 hours, 6 hours, 1 hour periods. And for the video - it might start now, you upload 30MBs and in 2 hours - the other 70Mbs.
You should use a Service when you are actively tracking or engaging with the user. Like for example Music applications, Running applications, etc.
And WM is something that underneath is using a Service, Broadcast Receivers, Room, etc. It hides a lot of complexity for you.
In my app I import gpx and kml files to display tracks and waypoints on the map. For this operation, I use about 5 methods. Everything works fine, unless I try to import several long gpx/kml tracks with exfilechoser.
The screen goes black for some seconds, and logcat says: skipped frames ( > 600).
How could I get these calculations of the UI?
Or how could I use AsyncTask with about 5 methods? Is this possible?
There are several methods.
Do calculations asynchronously. Android SDK provides Handler, IntentSevice, AsyncTask, HandlerThread to solve problems asynchronously. By the way, it is recommanded to use multi-thread solving heavy calclations.
Let server do calculations. Mobile devices is not suitable for calculating, calculations consume power and affect app performance.
By looking at your question i will suggest you to use handler with java normal multi threading concept.
I dont think Asyntask is a very good approach to do long running tasks on background.
It's good have do calculation on server side it reduces the overhead on mobile site.
I think you should use Service which was designed for this purpose. It is said in documentation:
A Service is an application component that can perform long-running
operations in the background.
You should remember about creating new thread in service.
Caution: A service runs in the main thread of its hosting process—the
service does not create its own thread and does not run in a separate
process (unless you specify otherwise). This means that, if your
service is going to do any CPU intensive work or blocking operations
(such as MP3 playback or networking), you should create a new thread
within the service to do that work.
So over the last few months I've created a fairly complex game that's near ready for release. The only problem left is that it is running as smoothly as I would hope and I think this is because of the way I have structured my threads. Right everything in my code is done through a surfaceview. All calculations, position updates, drawing, collisions, etc are done there. I was wondering if I am supposed to put all updates into one thread then handle only drawing in the surfacethread. Is this the proper way to do it, if so how would i implement that(asynctask,thread,handler,etc)?
Sure, you should avoid doing any time-consuming calculation in the UI Thread. You could also incur in an ANR error message.
You can either use:
AsyncTask, but be aware that it has some flaws and drawbacks. For example it isn't guaranteed to even start or complete.
IntentServices or HandlerThreads if you need to do operations that need to be executed sequentially in a worker thread
WorkerThreadPool if you need to execute true parallel tasks.
My application have to catch gps coordinates and send them periodically using an handler.
Within the onCreate method I do:
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 1, this);
and with that the onLocationChanged starts working.
At the end of the onCreate, I start an handler that every 2.5 seconds do some stuff.
I think this could not be the right way to achive my target, because the onLocationChanged() is not executed in a separate thread, so if the handler executes the onLocation could not be executed.
EDIT
I do not know how to concurrently manage the retrieval of GPS coordinates (how to execute the onLocationChanged).
The timer runs every 2.5 seconds a task and at the same time the onLocationChange have to set gps values that I need in the timer.
I fear that there may be problems with the onLocationChange that may not be performed at all.
I thought to use a AsyncTask, but how to execute it?
Although you have edited your question still not clear to me what exactly is your concern.
I'll give you some background information about concurrency, and let's see if it helps...
What is it
First, concurrency means a software designed to have more then one thread. That doesn't means that more then one thread will run in simultaneous, which only happens if you have a device with more then one core. If the device only has one core, only one thread will run at a time, and the system will switch between them.
As soon as your system is designed to have more then one thread, you must ensure that all your code (and used libraries) that are dealing with shared objects are thread safe.
Why should I need it
The most common reansons why you would need to use threads are:
You have a heavy piece of code that could be split into parts, and you have a device with more then one core. In this case, you could have a performance benefict from having two (or more) simoultaneous running threads dealing with parts of the work.
You have a blocking operation in your code (i.e. read from a socket). This should be moved to a separate thread to avoid blocking all your program until socket.read() returns.
Finally and the most commun one in Android, any long run operation (i.e. more then a couple of seconds) should be moved to a different thread from he one used by the UI (user interface), to avoid pour user experience and/or the ANR error.
Your situation
You refer that you are using LocationManager and an Handler. None of these classes imply using a different thread.
LocationManager uses the callback onLocationChange() to run the code you define in the UI thread.
Handler runs the code in the thread where the handler is assigned to. So if you created your handler in the UI thread, the handler callback will be run there as well.
Only if you create a new Thread (or any other class that does the same) you have a real multi-thread app that requires you to be carefull with shared objects.
Hope it helps. Let me know if you need more clarification.
Regards.
You can use the AsyncTask for fetching data.
refer this question.hope you will find the answer.
How To Get Location Using AsyncTask
I have an Android app that has separate things going on but are all basically threads (and definitely are threads to the Android debugger)
There are multiple animation listeners that loop and call each other
There is a countdown timer that is always counting down to zero after it is initiated
Now I need to consider adding more countdown timers. How many of these kind of looping processes can I have going on? In this particular implementation I am not concerned about performance, efficiency, etc, until it becomes apparent.
Insight appreciated
I would be very surprised to learn that you exhausted the number of threads you can use safely in an android application, as long as you are properly managing their lifetime and prevent "busy loops"and the like from occuring.
One thing I did learn though, I am pretty sure you can only have 5 asynctasks operational at any time, and they will arbitrarily continue to exist and get killed or respawned by themselves if you start new ones...ie if i turned an asynctask on then off five times the debugger will say 5 async threads operational, but I can continually toggle on and off as much as I want because the resource pool will kill the oldest dead asynctask.
There is no maximum that I know of. I can tell you, however, that you most likely don't NEED that many threads.
You can keep countdown listeners in a single thread using Android's Handler, specifically the postDelayed() method. Start a Looper in a separate thread, and use a Handler to manage the timeouts -- don't busy wait, or sleep-loop.
I don't believe countdown timer will create threads--it should simply add your task to a queue on your main thread from the looks of it.
All your listeners should take place on the same thread as well (there is a single thread that manages all listeners (for visible objects anyway).
So you probably aren't using anywhere near as many threads as you think you are. If you were creating a lot of threads I'd be worried--they are really hard to keep synchronized and may cost you a lot more than you'd gain, but with the structures listed I'd go ahead and allocate as many as you feel appropriate (but test for performance on a cheap device of course)