I have a service which contains a Timer and TimerTask for receiving data from Webservice in periods of time. When my TimerTask runs, the UI hangs until the Webservice process complete. How can I put my task in a thread to prevent the UI hanging?
My code:
Timer timerSyncFull = new Timer();
class taskSyncFull extends TimerTask {
#Override
public void run() {
hSyncFull.sendEmptyMessage(0);
}
};
final Handler hSyncFull = new Handler(new Callback() {
#Override
public boolean handleMessage(Message msg) {
procSyncFull();
return false;
}
});
public void procSyncFull() {
try {
// My webservice process
} catch (Exception e) {
}
}
#Override
public void onStart(Intent intent, int startId) {
timerSyncFull = new Timer();
timerSyncFull.schedule(new taskSyncFull(), 5*60*1000,
5*60*1000);
}
Use AsyncTasks or attach your Handler to another Looper thread.
I used the following code and my problem solved:
class taskSendMapMovements extends TimerTask {
#Override
public void run() {
hhSendMapMovements.sendEmptyMessage(0);
}
};
// /////////////////////
final Runnable rSendMapMovements = new Runnable()
{
public void run()
{
procSendMapMovements();
}
};
final Handler hhSendMapMovements = new Handler(new Callback() {
#Override
public boolean handleMessage(Message msg) {
performOnBackgroundThread(rSendMapMovements);
return false;
}
});
// /////////////////////
public void procSendMapMovements() {
try {
showToast("some text");
//My Main Process
} catch (Exception e) {
}
}
#Override
public void onStart(Intent intent, int startId) {
try {
timerSendMapMovements = new Timer();
timerSendMapMovements
.schedule(new taskSendMapMovements(),
10*60*1000,
10*60*1000);
//
} catch (NumberFormatException e) {
Toast.makeText(this, "error running service: " + e.getMessage(),
Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(this, "error running service: " + e.getMessage(),
Toast.LENGTH_SHORT).show();
}
}
final Handler hToast = new Handler(new Callback() {
#Override
public boolean handleMessage(Message msg) {
Toast.makeText(SrvDataExchange.this,
msg.getData().getString("msg"),
Toast.LENGTH_LONG).show();
return false;
}
});
private void showToast(String strMessage) {
Message msg = new Message();
Bundle b = new Bundle();
b.putString("msg", strMessage);
msg.setData(b);
hToast.sendMessage(msg);
}
public static Thread performOnBackgroundThread(final Runnable runnable) {
final Thread t = new Thread() {
#Override
public void run() {
try {
runnable.run();
} finally {
}
}
};
t.start();
return t;
}
Simply invoke your procSyncFull() method in thread or asyncTask.
final Handler hSyncFull = new Handler(new Callback() {
#Override
public boolean handleMessage(Message msg) {
Thread thread=new Thread()
{
public void run(){
procSyncFull();
}
}
return false;
}
});
private Handler webserviceCompletionHandler=new Handler()
{
#Override
public boolean handleMessage(Message msg) {
return false;
}
};
use AsyncTask carry out your execution in doInBackground() and populate it in onPostExecute()
AsyncTask Example
Related
I have got an infinite IntentService meant to enable scanner for all the time application is alive. And whenever there is a breakpoint - it works fine. But when I remove a breakpoint from a loop - it stops working after some time. And then again when I put a breakpoint - it starts working again. What the heck? How can I fix this?
protected void onHandleIntent(#Nullable Intent intent)
{
final Handler handler = new Handler();
handler.post(new Runnable()
{
#Override
public void run()
{
while(true)
{
if (!blocked)
{
blocked = true;
String received = GlobalAccess.scan.scan(1000);
if (received != null && !received.isEmpty())
{
//TODO: some stuff here
}
blocked = false;
}
else
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
}
}
}
});
}
EDIT
I have created my CustomService with
#Override
public void onCreate()
{
super.onCreate();
scheduledExecutorService = Executors.newScheduledThreadPool(1);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
final Handler handler = new Handler();
Runnable runnable = new Runnable()
{
#Override
public void run()
{
while(true)
{
if (!blocked)
{
blocked = true;
String received = GlobalAccess.scan.scan(1000);
if (!Objects.equals(received, null) && !received.isEmpty())
{
//TODO: some stuff here
}
blocked = false;
}
else
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
}
}
}
};
ScheduledFuture scheduledFuture = scheduledExecutorService.schedule(runnable, 0, TimeUnit.MILLISECONDS);
return START_STICKY;
}
But it has exact same bahavior as IntentService
Thanks to #CommonsWare I have managed to solve my problem.
This is the solution:
public class ScanService extends Service
{
ScheduledExecutorService scheduledExecutorService;
#Override
public void onCreate()
{
super.onCreate();
scheduledExecutorService = Executors.newScheduledThreadPool(1);
}
#Nullable
#Override
public IBinder onBind(Intent intent)
{
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Runnable runnable = new Runnable()
{
#Override
public void run()
{
String received = GlobalAccess.scan.scan(1000);
if (!Objects.equals(received, null) && !received.isEmpty())
{
//TODO: some stuff here
}
}
};
scheduledExecutorService.scheduleWithFixedDelay(runnable, 0, 50, TimeUnit.MILLISECONDS);
return START_STICKY;
}
}
I have a class that extends HandlerThread and implements Handler.Callback. I can't understand how to setup the Handlers to send messages back and forth to each other under this scheme. My Handler1 needs to talk to Handler2 and vice versa but because this is being implemented in a HandlerThread which has it's own looper I am not sure how to instantiate these objects. I'm simply stuck on how to apply this to syntax. I have posted my crack at it below. Any help is appreciated.
...
public class MyClass implements Runnable {
private Handler handler1 = null;
private Handler handler2 = null;
CyclicBarrier barrier = new CyclicBarrier(2);
class myThread extends HandlerThread implements Handler.Callback {
...
#Override
protected void onLooperPrepared() {
handler1 = new Handler(getLooper(), this){
#Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
}
};
handler2 = new Handler(getLooper(), this){
#Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
}
};
try {
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
Runnable runnable1 = new Runnable(){
#Override
public void run() {
Message message = Message.obtain();
message.setTarget(handler2);
message.obj = handler2;
message.sendToTarget();
}
};
Runnable runnable2 = new Runnable(){
#Override
public void run() {
Message message = Message.obtain();
message.obj = handler1;
message.setTarget(handler1);
}
};
}
#Override
public boolean handleMessage(Message reqMsg) {
//do some work
return true;
}
}
...
public void run() {
Thread mThread1 = new Thread(runnable1);
Thread mThread2 = new Thread(runnable2);
mThread1.start();
mThread2.start();
}
}
Here is the refactored code:
public class MyClass implements Runnable
{
private Handler handler1 = null;
private Handler handler2 = null;
CyclicBarrier barrier = new CyclicBarrier(2);
class myThread extends HandlerThread implements Handler.Callback
{
public myThread(String sName)
{
super(sName);
}
#Override
protected void onLooperPrepared() {
handler1 = new Handler(getLooper(), this){
#Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
}
};
handler2 = new Handler(getLooper(), this){
#Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
}
};
try {
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public boolean handleMessage(Message reqMsg) {
//do some work
return true;
}
}
Runnable runnable1 = new Runnable(){
#Override
public void run() {
Message message = Message.obtain();
message.setTarget(handler2);
message.obj = handler2;
message.sendToTarget();
}
};
Runnable runnable2 = new Runnable(){
#Override
public void run() {
Message message = Message.obtain();
message.obj = handler1;
message.setTarget(handler1);
}
};
public void run() {
Thread mThread1 = new Thread(runnable1);
Thread mThread2 = new Thread(runnable2);
mThread1.start();
mThread2.start();
}
}
}
please see the codes:
MainActivity.java:
protected void onCreate(Bundle savedInstanceState) {
...
TestClass tc = new TestClass();
tc.Test(new TestListener() {
public void onSuccess() {
//success do something
}
public void onFail() {
//fail do something
}
});
}
TestClass:
public class TestClass {
private static final int MSG_SUCCESS = 1;
private static final int MSG_FAIL = 0;
private TestListener listener = null;
public void Test(TestListener listener) {
this.listener = listener;
Log.d("test", "=======" + Thread.currentThread().getId());
HandlerThread ht = new HandlerThread("MyThread");
ht.start();
Thread thread = new Thread(mRunnable);
thread.run();
}
#SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SUCCESS:
Log.d("test", "on success");
if (listener != null) {
listener.onSuccess();
}
break;
case MSG_FAIL:
if (listener != null) {
listener.onFail();
}
break;
}
}
};
Runnable mRunnable = new Runnable() {
#Override
public void run() {
Log.d("test", "=======" + Thread.currentThread().getId());
try {
Log.d("test", "start sleep");
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d("test", "sleep end");
mHandler.obtainMessage(MSG_SUCCESS).sendToTarget();
}
};
}
TestListener:
public interface TestListener {
public void onSuccess();
public void onFail();
}
print log:
07-30 15:15:03.565: D/test(2202): =======1
07-30 15:15:03.565: D/test(2202): =======1
Slaver Thread have no effect??
This is the problem:
thread.run();
That's running the Runnable code synchronously, in the existing thread. You meant:
thread.start();
first of all you will have to show() your Toast msgs:
Toast.makeText(getApplicationContext(), "onsuccess", Toast.LENGTH_SHORT).show();
and you want to start() your thread:
thread.start();
I have a service which contains a Timer and TimerTask for receiving data from Webservice in periods of time. everything works fine except Toast. I want to show a Toast to user in procSendMapMovements but i get exception. How can I use Toast in it?
class taskSendMapMovements extends TimerTask {
#Override
public void run() {
hhSendMapMovements.sendEmptyMessage(0);
}
};
// /////////////////////
final Runnable rSendMapMovements = new Runnable()
{
public void run()
{
procSendMapMovements();
}
};
final Handler hhSendMapMovements = new Handler(new Callback() {
#Override
public boolean handleMessage(Message msg) {
performOnBackgroundThread(rSendMapMovements);
return false;
}
});
// /////////////////////
public void procSendMapMovements() {
try {
Toast.makeText(SrvDataExchange.this,
"some texts"
Toast.LENGTH_SHORT).show();
// exception here
// my process
} catch (Exception e) {
}
}
#Override
public void onStart(Intent intent, int startId) {
try {
timerSendMapMovements = new Timer();
timerSendMapMovements
.schedule(new taskSendMapMovements(),
10*60*1000,
10*60*1000);
//
} catch (NumberFormatException e) {
Toast.makeText(this, "error running service: " + e.getMessage(),
Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(this, "error running service: " + e.getMessage(),
Toast.LENGTH_SHORT).show();
}
}
public static Thread performOnBackgroundThread(final Runnable runnable) {
final Thread t = new Thread() {
#Override
public void run() {
try {
runnable.run();
} finally {
}
}
};
t.start();
return t;
}
Create a handler to display toast.
Use following:
where you want to display toast call:
//printToast.sendEmptyMessage();//If you dont want to send no paramter
//if you want to send some object to handler
/*
Message msg=printToast.obtainMessage();
msg.obj=objToSent;
printToast.sendMessage(msg);
*/
final Handler printToast= new Handler(new Callback() {
#Override
public boolean handleMessage(Message msg) {
Toast.makeText....;
}
});
**
Handler printToast= new Handler(new Callback() {
#Override
public boolean handleMessage(Message msg) {
Toast.makeText....;
}
});
your Runnable
{
run()
{
do what ever you want
printToast.sendMessage(printToast.obtainMessage());
}
}
**
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();
}