In the last years working with multitasking on Android was a bit tricky but after a lot of study I have worked out this. The playground was full of scattered objects with a high learning curve and with one only exit: abandon all frameworks and pass on base objects.
At the end of the study, all limits to one and only simple object on which to build all you personal framework: the Thread
object.
Your app, usually, is a single process in which more threads are started. The most important thread that you know is the “Main thread” or “UI Thread”; in this thread all User Interfaces tasks are worked out. If you have some particular dependency as Firebase or Crashlytics, then other threads are started in background and in a completely transparent manner.
Now let’s start with the simplest multitasking:
new Thread(() -> {
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST);
myBackgroundMethod.start();
}).start();
With this simple line of code a new world opens to you:
The multi-threading
Don’t bother with Processes and threads overview or Running Android tasks in background threads because is a loss of time, don’t bother with Handlers, Loopers, AsyncTasks, and so on because are all deprecated. The only one that exists in multitasking is Thread
.
This simple new Thread(...).start();
start your function in the background and the setThreadPriority(...)
set itself to be with the lowest priority so you can make other things on the main thread like components initializations, starting of advertising services, reading databases or settings from file on the file system, download of data from the internet and so on… Your thread will go on by itself without disturbing the user interface and avoiding ANRs, the infamous Application Not Responding error message displayed when your app is doing much work in foreground and blocks the user interface.
With new Thread().start()
all you background work is done VERY in background and in multitasking.
You can start all the threads you want but keep in mind that if 2 or more thread access the same memory variable, then here can start a lot of subtle problems named
Race conditions
(with race data). I will explain this with an example in the real world.
If I have in my bank account 200$ and I have to make a payment of 100$ and after a payment of 150$, if this two operations are made consequently then all is going well, the second payment cannot be done:
I have to pay 100$, do I have minimum 100$ on my account? yes I have 200$, ok make the payment;
I have to pay 150$, do I have minimum 150$ on my account? no, I have only 50$, the second transaction cannot be done and is correctly handled.
But if the two operations are made approximately in the same time (as assigning two different values at the same variable, let’s talk about some nanosecond), then a different scenario is seen:
I have to pay 100$, do I have minimum 100$ on my account? yes I have 200$, ok make the payment;
in the same time:
I have to pay 150$, do I have minimum 150$ on my account? yes, I have 200$, ok make the payment. This last transaction has not been correctly handled.
This is a race condition, and is generated by incorrect timing between two operations. To avoid this situation you must implement a semaphore, in this case when the first operation is going on, a lock on the bank account will occur; after the end of the first operation the lock is removed. When the second operation starts, at first checks the lock, and then waits until the lock is removed…
Race condition
between threads cause bugs that are hard to catch.
Finally, let’s say that your background thread will update a progress bar, that is an element in the User Interface and cannot be updated from a secondary thread; you can make with this simple
activity.runOnUiThread(() -> progressCallback.onProgress(value));
from you thread.
Hi friends, its impressive piece of writing on the topic of tutoringand fully explained, keep it up all the time.