Robolectric (3.1) should be able to execute runnable posted to the handler.
#Test
public void shouldExecuteRunnable() throws Exception {
final CountDownLatch signal = new CountDownLatch(1);
final boolean[] result = {false};
Runnable runnable = new Runnable() {
#Override
public void run() {
result[0] = true;
signal.countDown();
}
};
HandlerThread handlerThread = new HandlerThread("HandlerThread");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
handler.post(runnable);
Robolectric.flushBackgroundThreadScheduler();
Robolectric.flushForegroundThreadScheduler();
signal.await(5, TimeUnit.SECONDS);
Assert.assertTrue(result[0]);
}
Test fails on assertion. Am I missing something?
Any help will be appreciated.
#Test
public void shouldExecuteRunnable() throws Exception {
final boolean[] result = {false};
Runnable runnable = new Runnable() {
#Override
public void run() {
result[0] = true;
}
};
ShadowLooper.pauseMainLooper();
Handler handler = new Handler();
handler.post(runnable);
ShadowLooper.runMainLooperOneTask();
Assert.assertTrue(result[0]);
}
Had the same issue,
This fixed it:
ShadowLooper threadShadow = shadowOf(thread.getLooper());
threadShadow.runOneTask();
Related
Im pretty new to android and I'm trying to make an imagebutton in android studio that changes images at set inervals. I tried to just use wait and put it into a different thread but that doesn't seem to work. All I want if for the image to change while also still allowing for a mp3 to be played whilst doing so.
Runnable r = new Runnable() {
#Override
public void run()
{
synchronized (this)
{
try
{
wait(1000);
ank.setImageResource(R.drawable.shank2);
wait(1000);
ank.setImageResource(R.drawable.shank3);
wait(1000);
ank.setImageResource(R.drawable.shank4);
wait(1000);
ank.setImageResource(R.drawable.shank5);
}
catch (Exception e) {}
}
}
};
Thread myThread = new Thread(r);
myThread.start();
Simple way:
public void changeImages() {
Handler uiHandler = new Handler();
uiHandler.postDelayed(new Runnable {
#Override
public void run() {
ank.setImageResource(R.drawable.shank1);
}
}, 1000);
uiHandler.postDelayed(new Runnable {
#Override
public void run() {
ank.setImageResource(R.drawable.shank2);
}
}, 2000);
...
}
Better way:
public void changeImages() {
int[] images = new int[] { R.drawable.shank1, R.drawable.shank2 ... }
long delay = 1000;
Handler uiHandler = new Handler();
for (int imageRes : images) {
uiHandler.postDelayed(new Runnable {
#Override
public void run() {
ank.setImageResource(imageRes);
}
}, delay);
delay += 1000;
}
}
The best way
final Handler uiHandler = new Handler();
final Queue<Integer> queue = new LinkedBlockingQueue<>();
void changeImages() {
queue.add(R.drawable.shank1);
queue.add(R.drawable.shank2);
...
loopImages();
}
void loopImages() {
if (!queue.isEmpty()) {
uiHandler.postDelayed(new Runnable() {
#Override
public void run() {
ank.setImageResource(queue.poll());
}
}, 1000);
}
}
I want to create another thread to loop itself and perform something.
May I know any mistake I done? Because it just perform single time and stop.
public class LooperClazz extends Thread {
private MessageQueue messageQueue;
private Context context;
private long counter = 0;
public LooperClazz(Context context){
this.context = context;
}
#Override
public void run() {
Looper.prepare();
long threadId1 = Thread.currentThread().getId(); //new thread
final Handler responseHandler = new Handler(Looper.getMainLooper()) {
#Override
public void handleMessage(Message msg) {
long mainThreadId = Thread.currentThread().getId(); //1
//Here success to Toast something.
}
};
messageQueue = Looper.myQueue();
messageQueue.addIdleHandler(new MessageQueue.IdleHandler() {
#Override
public boolean queueIdle() {
//I'm expecting running this in a loop, but it not, why?
long threadId2 = Thread.currentThread().getId();
//Same as threadId1
counter++;
Message msg = new Message();
msg.obj = counter+ "";
responseHandler.sendMessage(msg);
SystemClock.sleep(3000);
return true;
}
});
Looper.loop();
}
}
In MyApplication, I just start it with
new LooperClazz(context).start();
I have try to update my TextView in Thread, but not able to do, below code shows my try
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
String add = null;
public void run() {
add = Util.getLocationCityName(String.valueOf(ltlng.latitude),String.valueOf(ltlng.longitude));
handler.post(new Runnable() {
public void run() {
LogUtil.d("add" + add);//i can get the add value
vImei.setText(add);
}
});
}
};
new Thread(runnable).start();
i can able to get the add value which is inside handler but values are not update to my textview, dont know what mistake i have done
Try to init Handler with looper
final Handler handler = new Handler(Looper.getMainLooper());
Also you can try :
private LooperThread mLooperThread;
class LooperThread extends Thread
{
public Handler mHandler;
public void run()
{
Looper.prepare();
mHandler = new Handler()
{
public void handleMessage(Message msg)
{
vImei.setText(msg.getData().getString("ADD"));
}
};
Looper.loop();
}
}
create Looper :
mLooperThread = new LooperThread();
mLooperThread.start();
and when you need to update :
Bundle bundle = new Bundle();
bundle.putString("ADD", add);
Message msg = Message.obtain();
msg.setData(bundle);
mLooperThread.mHandler.sendMessage(msg);
//Global Initialize
String add = "";// not null
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
public void run() {
add = Util.getLocationCityName(
String.valueOf(ltlng.latitude),
String.valueOf(ltlng.longitude));
handler.post(new Runnable() {
public void run() {
LogUtil.d("add" + add);//i can get the add value
vImei.setText(add);
}
});
}
};
new Thread(runnable).start();
I hope it helps you.. :)
An other solution which solves your problem is the usage of an AsyncTask
AsyncTask<Void, Void, String> asyncTask = new AsyncTask<Void, Void, String>(){
#Override
protected String doInBackground(Void... params) {
// runs on its own thread
return Util.getLocationCityName(
String.valueOf(ltlng.latitude),
String.valueOf(ltlng.longitude));
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// runs on the UI Thread to Update your Views
LogUtil.d("add" + result);
vImei.setText(result);
}
};
asyncTask.execute();
Please try this,
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
String add = null;
public void run() {
add = Util.getLocationCityName(
String.valueOf(ltlng.latitude),
String.valueOf(ltlng.longitude));
runOnUiThread(new Runnable(){
public void run() {
LogUtil.d("add" + add);//i can get the add value
vImei.setText(add);
}
});
}
};
new Thread(runnable).start();
I believe I'm not understanding how Handler can pass/receive messages.
I have a handler created on a different thread, and then have the main thread send it a message. Here is how I did it
public void startAniHandlerThread(int timer){
final int sleeptime = timer;
int test2;
Thread thread1 = new Thread(){
public void run(){
Looper.prepare();
Log.v("loop","looping");
Handler handler = new Handler(){
#Override
public void handleMessage(Message inputMessage) {
Log.v("Thread handler", "checking");
if(inputMessage.what == 10) {
if (inputMessage.arg1 == 2) {
Log.v("Thread handler", "stop");
} else if (inputMessage.arg1 == 1) {
Log.v("Thread handler", "continue");
} else{
Log.v("nothing", "nothing");
}
}
}
};
Looper.loop();
}
};
thread1.start();
}
Here is how I attempted to send a message to it from the UI thread:
public void stopAniHandlerThread(){
Handler newHandler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
return false;
}
});
Runnable newRunable = new Runnable() {
#Override
public void run() {
Handler handler = new Handler();
Message message = new Message();
message.what = 10;
message.arg1 = 2;
handler.sendMessage(message);
}
};
newHandler.postDelayed(newRunable, 2000);
}
Here is the Log I get(I'm expected this to get called, but it doesn't:
Log.v("Thread handler", "stop");
V/stopAniHandlerThread﹕ posting
V/loop﹕looping
Implementing a Thread by providing a new class that extends Thread and overriding its run() method is new to me. I've tried all day to get it to work. Here's my code:
/*
* see http://developer.android.com/reference/java/lang/Thread.html
*/
class threadClass extends Thread {
private Handler mHandler;
private Message mMsg;
// constructor
public threadClass(Handler handler, Message msg) {
// do something like save the Handler reference
mHandler = handler;
mMsg = msg;
}
#Override
public void run() {
// do some background processing, call the Handler?
mHandler.sendMessage(mMsg);
}
}
public Thread passHandlerToThread(Handler handler) {
handler.sendEmptyMessage(10);
Message msg = Message.obtain();
msg.what = 10;
Thread thread = new threadClass(handler, msg);
return thread;
}
private Handler localHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
int what = msg.what;
if (what == 10) Log.i("localHandler", "what: " + what);
}
};
public void startThread() {
Thread thread = passHandlerToThread(localHandler);
thread.start();
}
I call startThread() in my LocalService onCreate() but nothing happens. What am I doing wrong? I was expecting localHandler() to be called twice: once in passHandlerToThread() and again in run().
Do something like this:
private final Handler handler = new Handler();
// toast runnables
final Runnable updateTwitterNotification = new Runnable() {
#Override
public void run() {
dismissProgressSpinner();
Toast.makeText(getBaseContext(), "Tweet sent!", Toast.LENGTH_LONG).show();
}
};
final Runnable updateCreateError = new Runnable() {
#Override
public void run() {
Toast.makeText(getBaseContext(), "Tweet error!", Toast.LENGTH_LONG).show();
}
};
postMessageInThread();
//implementation:
private void postMessageInThread() {
Thread t = new Thread() {
#Override
public void run() {
try {
connectToTwitterService() // or whatever
handler.post(updateTwitterNotification);
} catch (Exception ex) {
Log.e(TAG, "Error sending msg", ex);
handler.post(updateCreateError);
}
}
};
t.start();
}