run code in a non-UI thread android - android

I have an image application and I'm playing music while the images are displayed.
Right now, I have both the functionality in the UI thread.
I want to move the music playback part of it into another thread that is different from the UI thread.
How do I achieve this?
The complication if I use handlers and runnables:
the run() has to have everything that is to be executed
but the music code is scattered all over the place because it is event based and there's a different piece of code to execute each time
so the only way i can implement this with handler and runnable is if I have several runnables each doing a particular function
which means that all the music code will not run in the same thread, they would run in different threads
which is not a good thing.
So how do you do this?

I would suggest creating a Service with a Binder - you would then have a handle to it. In Service create an Executor (singular or multiple Threads in pool - depends on your application structure and events you have; so does a Queue implementation) and then just pass music events to the executor.

This is what I did:
public static void startTrack() {
PLAYER_STATE = IS_PLAYING;
/*Setup the handler and runnable*/
mMusicHandler = new Handler() {
};
mMusicRunnable = new Runnable() {
public void run() {
Log.d(TAG,"inside Music Runnable");
try {
mPlayer.start();
} catch (IllegalStateException e) {
Log.d(TAG,"ILLEGAL STATE-START");
handleIllegalState();
}
}
};
mMusicHandler.post(mMusicRunnable);
}
So only the start part of the music setup is done on a different thread.

Related

Thread.sleep() vs handler.postDelay() to execute network call in every 30sec

I want perform a network call in every 30sec to push some metrics to Server. Currently I am doing it using thread.sleep(). I found some articles saying thread.sleep() has some drawbacks. I need to know am I doing it right? or Replacing the thread with Handler will improve my code?
public static void startSending(final Context con) {
if (running) return;
running = true;
threadToSendUXMetrics = new Thread(new Runnable() {
#Override
public void run() {
do {
try {
Thread.sleep(AugmedixConstants.glassLogsPushInterval);
} catch (InterruptedException e) {
mLogger.error(interrupt_exception + e.getMessage());
}
// to do to send each time, should have some sleep code
if (AugmedixConstants.WEBAPP_URL.equals(AugmedixConstants.EMPTY_STRING)||!StatsNetworkChecker.checkIsConnected(con)) {
Utility.populateNetworkStat();
mLogger.error(may_be_provider_not_login_yet);
} else
sendUXMetrics();
} while (running);
if (!uxMetricsQueue.isEmpty()) sendUXMetrics();
}
});
threadToSendUXMetrics.start();
}
If You are using only one thread in the network, then usage of the thread.sleep() is fine. If there are multiple threads in synchronization, then the thread.sleep() command will block all the other threads that are currently running.
As per the details you've provided, there is only one thread present which isn't blocking any other active threads which are running in synchronization, so using thread.sleep() shouldn't be a problem.
Use Handler.postDelayed to schedule tasks if you are working in UI Thread and Thread.sleep if you are working in background thread.
Apparently you are sending some data using network, you must do it in the background thread, hence Thread.sleep is recommended.
Simple is:
Thread.sleep(millisSeconds): With this method, you only can call in background tasks, for example in AsyncTask::doInBackground(), you can call to delay actions after that. RECOMMENDED CALL THIS METHOD IN BACKGROUND THREAD.
Handler().postDelayed({METHOD}, millisSeconds): With this instance, METHOD will trigged after millisSeconds declared.
But, to easy handle life cycle of Handler(), you need to declare a Handler() instance, with a Runnable instance. For example, when your Activity has paused or you just no need call that method again, you can remove callback from Handler(). Below is example:
public class MainActivity extends Activity {
private Handler mHandler = Handler();
public void onStart(...) {
super.onStart(...)
this.mHandler.postDelayed(this.foo, 1000)
}
public void onPaused(...) {
this.mHandler.removeCallback(this.foo)
super.onPaused(...)
}
private Runnable foo = new Runnable() {
#Override
public void run() {
// your code will call after 1 second when activity start
// end remove callback when activity paused
// continue call...
mHandler.postDelayed(foo, 1000)
}
}
}
The code above just for reference, I type by hand because don't have IDE to write then copy paste.

Why does runOnUiThread() not work inside Service?

I am creating an application that needs to update values every minute even if the app isn't running.
Of course, I have set up a simple Service to do that. I have debug messages set up to tell me when the Service starts, when it updates (every minute), and when it closes. I also have a message telling me when the values update inside a runOnUiThread() method. All of my messages activate except for the one in the runOnUiThread(). Is there something I'm doing wrong (of course there is)? What do I need to change?
Code:
#Override
public void handleMessage(Message message) {
try {
if (!serviceStarted) {
serviceStarted = true;
serviceTest = true;
while (serviceStarted) {
new MainActivity().runOnUiThread(new Runnable() {
public void run() {
OverviewFragment.refresh(getApplicationContext());
System.out.println("yay");
}
});
Thread.sleep(((1 /* minutes */) * 60 * 1000));
System.out.println("Updated values through service.");
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
stopSelf(message.arg1);
}
So there's no need to do that, unless you're creating a Thread inside
of it
Gabe Sechan's answer is correct.
But if you are using a separate thread then instead of following code:
new MainActivity().runOnUiThread(new Runnable() {
public void run() {
OverviewFragment.refresh(getApplicationContext());
System.out.println("yay");
}
});
Try, this code:
new Handler(Looper.getMainLooper()).post(new Runnable() {
public void run() {
OverviewFragment.refresh(getApplicationContext());
System.out.println("yay");
}
});
As per Android docs
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).
You can't create an Activity by calling new. It doesn't initialize properly that way.
Also, Services by default run on the UI thread. So there's no need to do that, unless you're creating a Thread inside of it. If you are- runOnUIThread is just syntactic sugar for posting a runnable to a handler. So you can just do that instead.
Try using a handler or LocalBroadcastManager to send a message to the activity.
See this question: Accessing UI thread handler from a service
You can use Looper.getMainLooper() within a Handler to post a Runnable that executes whatever you're trying to execute.
A good alternative though, like jinghong mentioned, is to use broadcasts - in other words, use a different pattern.

Why do we use a Handler? Why we don't call an interface element inside a Runnable object?

Whenever this code is executed the application crashes, but when a handler is used the application works as expected.
Runnable r = new Runnable() {
#Override
public void run() {
long futuretime = System.currentTimeMillis()+10000;
while(System.currentTimeMillis()<futuretime){
synchronized (this){
try {
wait(futuretime - System.currentTimeMillis());
} catch (Exception e) {}
}
}
//this code needs to be inside a Handler ??
TextView time = (TextView)findViewById(R.id.timedisplay);
time.setText("Changed Man!!");
//this code needs to be inside a Handler ??
}
};
Thread thread = new Thread(r);
thread.start();
}
Here all the answer have mentioned use of handler is used in Android with UI thread. But Let me add more to it.
If you have gone Android documentation/tutorial you would know that
When an application component starts and the application does not have
any other components running, the Android system starts a new Linux
process for the application with a single thread of execution. By
default, all components of the same application run in the same
process and thread (called the "main" thread or uiThread).
for more info refer
Now coming to your mentioned example; you have created another thread using Runnable...so there might be scenario you need thread(s) other then just mainThread in Android Application.
If you are good in JAVA Threading concept then you would know how Interthread communication happens and for different ways how it can be done refer
So coming back to question in android we have mainThread or uiThread so called which holds our ui i.e. view component. These component are private to mainThread so other thread cannot access it...which has been mentioned in previous answer. This is where Handler comes into picture you do not need to worry how your message would be passed from one thread to another.
Handler
There are two main uses for a Handler: (1) to schedule messages and
runnables to be executed as some point in the future; and (2) to
enqueue an action to be performed on a different thread than your
own.When posting or sending to a Handler, you can either allow the
item to be processed as soon as the message queue is ready to do so,
or specify a delay before it gets processed or absolute time for it to
be processed. The latter two allow you to implement timeouts, ticks,
and other timing-based behavior.
For more info refer docs AND
For more info with handler and UI thread
Code that deals with the UI should be run on the UI (main) thread.
You (probably) create a handler on the UI thread, so all messages sent via it will run on that thread too.
The Runnable is use for background process(background thread) and textview is in your UI thread so background thread can't communicate with foreground thread so it will gives you error and crashes your application.you can also use the runOnUiThread. example.
Runnable r = new Runnable() {
#Override
public void run() {
long futuretime = System.currentTimeMillis()+10000;
while(System.currentTimeMillis()<futuretime){
synchronized (this){
try {
wait(futuretime - System.currentTimeMillis());
} catch (Exception e) {}
}
}
try {
// code runs in a thread
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView time = (TextView)findViewById(R.id.timedisplay);
time.setText("Changed Man!!");
}
});
} catch (final Exception ex) {
Log.i("---","Exception in thread");
}
}
};
Thread thread = new Thread(r);
thread.start();
The reason why your app crashes is that you modify View from a non-UI thread.
If you do it using a Handler that belongs to UI-thread this works as expected.Update
If you need to run Runnable to modify UI you may choose from:
1) yourActivity.runOnUiThread(Runnable r)
2) yourHandlerOnUIThread.post(Runnable r)
3) yourView.post(Runnable r)

Android - efficiently schedule a task periodically?

I've got this code to schedule a task every so often:
final Handler handler = new Handler();
Runnable update = new Runnable() {
#Override
public void run() {
try{
runOnUiThread(new Runnable(){
public void run(){
lbl.setText(info);
cpb.setProgress(Float.valueOf(textInfo);
}
});
handler.postDelayed(this, 1000);
}
catch (Exception e) {
// TODO: handle exception
}
}
};
I want to constantly update the UI (every second, etc). The code works, however, the interface starts lagging. After the code iterates the task a few times the interface stops responding.
Is there any way I can schedule a task to repeat periodically without overloading the memory and without the interface lagging.
Assuming lbl is a TextView and cpb is a ProgressBar, your code will not considerably lag any device as it is. The problem lies somewhere else. Also, you appear to have missed a closing bracket on (Float.valueOf(textInfo);.
As an aside, you are unnecessarily using runOnUiThread inside the Runnable from what I can see. When you create a new Handler() it is implicitly linked to the calling thread's Looper, which I am assuming is the UI thread. In which case, the update Runnable will already be running on the UI thread. EDIT: This should not be the cause of the lag for the record, since iirc runOnUiThread checks if it is being executed on the UI thread then just runs it immediately, without doing another post.

Task queue on Android like in GCD on iOS?

Is there such a thing as task queue on Android? I know that it can be written by hand but is there a ready to use library for that?
I'm not sure if there would be a library for this one, as Android already provides the high-level building blocks for what you're trying to achieve.
Handler
If I understood you correctly, you want to post tasks from any thread to be queued and executed one-by-one on a dedicated thread. This is very much what Android Handler is meant for.
Key traits of Handler, Looper and MessageQueue
A Handler is tied to a single Looper.
Each Looper has an associated MessageQueue
Handler uses a Looper underneath to enqueue and dequeue messages in a thread-safe manner into the Looper's MessageQueue.
Handler objects are inherently thread-safe and hence can be passed around to other threads safely.
You can have multiple Handler objects tied to a same Looper. This is useful if you want to process different kinds of messages using different Handlers. In this case, you are guaranteed that only one of the Handlers will process a Message/Runnable for a given Looper. The Looper takes care of dispatching the Message to the right Handler.
If you're already familiar with the Message Queue paradigm for communicating between 2 threads (or similar golang's buffered channel pattern), Handler is just a high level class which lets you use this pattern easily.
Example for using Handler to send/receive Messages, post Runnables
// BEGIN One-time Initialization
// Create a Handler thread
// This provides the looper for the Message Queue and
// will be processing all your messages (i.e. tasks).
handlerThread = new HandlerThread("SomeThreadName");
// Start the Handler Thread
// The thread will block (using the looper) until it
// receives a new message
handlerThread.start();
// Create a Message Handler which you can use to
// post and process messages
// The same Handler can also be used to post a Runnable which will get
// executed on handlerThread
handler = new CustomHandler(mHandlerThread.getLooper());
// END One-time Initialization
// Different ways to post a message to the Handler Thread
// These calls are thread-safe, can be called safely and
// concurrently from multiple threads without race conditions
handler.sendEmptyMessage(MESSAGE_ID_1);
handler.sendEmptyMessage(MESSAGE_ID_2);
handler.sendMessage(handler.obtainMessage(MESSAGE_ID_3, obj1));
handler.sendMessage(handler.obtainMessage(MESSAGE_ID_4, value, obj1));
handler.sendMessage(handler.obtainMessage(MESSAGE_ID_5, value1, valu2, obj1));
// Post a runnable on the Handler Thread
// This is thread-safe as well
// In fact all methods on the Handler class are thread-safe
handler.post(new Runnable() {
#Override
public void run() {
// Code to run on the Handler thread
}
});
// A skeleton implementation for CustomHandler
// NOTE: You can use the Handler class as-is without sub-classing it, if you
// intend to post just Runnables and NOT any messages
public class CustomHandler extends Handler {
public CustomHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message message) {
if (message != null) {
// Process the message
// The result can be sent back to the caller using a callback
// or alternatively, the caller could have passed a Handler
// argument, which the Handler Thread can post a message to
switch (message.what) {
case MESSAGE_ID_1:
// Some logic here
break;
case MESSAGE_ID_2:
// Some logic here
break;
case MESSAGE_ID_3:
// Some logic here
break;
case MESSAGE_ID_4:
// Some logic here
break;
case MESSAGE_ID_5:
// Some logic here
break;
// Add more message types here as required
}
}
}
}
// After you're done processing all messages and you
// want to exit the Handler Thread
// This will ensure that the queue does not accept any
// new messages, and all enqueued messages do get processed
handlerThread.quitSafely();
Deviations from the above example
Although I've used HandlerThread in the above example, it is not mandatory to use it. You can even use the Looper calls directly, i.e. Looper.prepare() and Looper.loop() to run your own message loop in a thread.
As already mentioned in the comments, you do not need to sub-class the stock Handler if you do not intend to handle any messages.
You can communicate between multiple threads easily by using a Handler for each thread that needs to receive the message.
There are methods in Handler to schedule message delivery and Runnable execution in the future as well.
Android's framework internally uses Handler extensively for managing component lifecycle events (onPause, onResume, etc.).
AsyncTask
AsyncTask is another alternative to scheduling tasks on a different thread. . I won't go into too much detail of its implementation, as the Android developer documentation already describes it in detail.
I usually use AsyncTasks for tasks that I know I'll use a background thread for a long time (easily >= 100 ms at least). Some examples which fall into this category I can think of are Binder IPC, RPC calls, Network calls, Background downloads, etc.
On the other hand, Handler is more tailored for situations focussed on processing more number of messages as quickly as possible. In other words avoid performing any blocking operation in handleMessage(). You can write lock-free code easily using Handler, it manages all the locking for you when enqueuing and dequeuing messages.
In fact AsyncTask can be used in combination with Handler by splitting the work into a fast part (taken care by Handler) and a slow part (taken care by AsyncTask).
PS: Although tangential to the question, if you're interested in the Message Queue paradigm; do take a look at LMAX Disruptor, which is a high performance inter-thread Message Queue library. Their design document explains pretty well, which parts of the Message Queue, need locking/atomic access.
I've also looked around for something like GCD for Android. While Handlers and AsyncTasks are awesome the beauty of GCD (in my humble opinion) is that you can dispatch a workload on a background thread to do the heavy lifting. When the execution is done it i easy to execute the UI updates on the UI thread.
Since I did not find anything me and my school mate decided to create one of our own.
You can find it at:
ICDispatch on github
Basically all you need to do is to declare an Application class that extends ICDispatchApplication instead of Application and when you want to dispatch something you just call on
App.executeOn(int queue, ICBlock block);
Example:
App.executeOn(ICDispatch.NORMAL, new ICBlock(){
public void run(){
//do stuff...
App.executeOn(ICDispatch.MAIN, new ICBlock(){
public void run(){
//post result to UI thread.
}
}
}
});
The worst part is that there will be a lot of indentation. In order to minimize indentation you could use lambda notation:
App.executeOn(ICDispatch.NORMAL, ()->{
//do stuff...
//do some more...
//then even more
App.executeOn(ICDispatch.MAIN,() -> {
//Post result on UI thread.
}
});
At the moment ICDispatch supports LOW, NORMAL, HIGH, MAIN and CONCURRENT queueing. Features will be added as they are implemented.
I don't know iOS so I'm not sure if it is the same but in Android you have the ScheduledThreadPoolExecutor
For anyone finding this thread now, there is a new framework available called Bolts. It has tasks and continuations and can wait on multiple tasks to finish, like GCD.
I take this sample from Telegram Code :
You can declare extended thread for this approach
public static volatile DispatchQueue globalQueue = new DispatchQueue("globalQueue");
the class is :
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import java.util.concurrent.CountDownLatch;
public class DispatchQueue extends Thread {
private volatile Handler handler = null;
private CountDownLatch syncLatch = new CountDownLatch(1);
public DispatchQueue(final String threadName) {
setName(threadName);
start();
}
private void sendMessage(Message msg, int delay) {
try {
syncLatch.await();
if (delay <= 0) {
handler.sendMessage(msg);
} else {
handler.sendMessageDelayed(msg, delay);
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
public void cancelRunnable(Runnable runnable) {
try {
syncLatch.await();
handler.removeCallbacks(runnable);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
public void postRunnable(Runnable runnable) {
postRunnable(runnable, 0);
}
public void postRunnable(Runnable runnable, long delay) {
try {
syncLatch.await();
if (delay <= 0) {
handler.post(runnable);
} else {
handler.postDelayed(runnable, delay);
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
public void cleanupQueue() {
try {
syncLatch.await();
handler.removeCallbacksAndMessages(null);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
#Override
public void run() {
Looper.prepare();
handler = new Handler();
syncLatch.countDown();
Looper.loop();
}
}
and the Caller :
globalQueue.postRunnable(new Runnable() {
#Override
public void run() {
/* do here what you want */
}
});
You should check Handler & Loopers
Handlers, by default (*), like dispatch_get_main_queue() and you can post any block (Runnable instance) of code. Same approach also acquired with Context.runOnUiThread() and View.post(Runnable)
(*) Default constructor of Handler inherits the current thread's Looper instance (RunLoop in iOS) and queues (via handlerInstace.post...() methods) Runnable instances on Looper.
For more advance usage. You can create your own Looper instance (be aware it is a bit tricky :)). Still this might be handy...
Also for more advance usage, Handlers are the best tools i come across on Android (and yes, i miss them on iOS) for messaging inside application (inter-process communication something i guess). They might be customized to handle posted messages, bla, bla...

Categories

Resources