In my project, I want to implement a timer in another thread that counts down the time spent executing a certain method in my application, and do something if it is taking too much time. When executing the MyManager.startCommand() method, the application is freezing and I don't know why since I think I am not doing anything on the UI thread. Is there anything wrong with my code?
I had originally asked this question and was not experiencing an app freeze, so I don't think it's because I'm sleeping the thread: Runnable posted in another runnable not executed.
public class MyManager{
private MyManager sInstance;
private HandlerThread mHandlerThread;
private Handler mHandler;
private Runnable mTimeoutTimer;
public static MyManager getInstance(){
if(sInstance == null){
sInstance = new MyManager();
}
return sInstance;
}
private MyManager(){
mHandlerThread = new HandlerThread("mHandlerThread");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
mTimeoutTimer = new Runnable() {
#Override
public void run() {
Log.e(“RUNNABLE RUNNING!”);
}
};
public class MyCommand {
private Runnable myRun;
public MyCommand(){
myRun = new Runnable() {
#Override
public void run() {
MyManager.getInstance().startTimeoutTimer();
MyCommand.this.run();
}
};
}
public void execute() {
myRun.run();
}
abstract public void run();
}
private void startTimeoutTimer(){
mHandler.post();
}
public void startCommand(){
new MyCommand().execute();
}
}
And how I'm using a MyCommand object:
MyCommand command =
new MyCommand() {
#Override
public void run() {
//make api call that happens in another thread
}
};
So I am basically trying to create the timeout timer for that API call.
Try this:
Just wrap your first runnable in a Thread.
public class MyManager{
private MyManager sInstance;
private HandlerThread mHandlerThread;
private Handler mHandler;
private Runnable mTimeoutTimer;
public static MyManager getInstance(){
if(sInstance == null){
sInstance = new MyManager();
}
return sInstance;
}
private MyManager(){
mHandlerThread = new HandlerThread();
mHandler = new Handler(mHandlerThread.getLooper());
mTimeoutTimer = new Runnable() {
#Override
public void run() {
Log.e(“RUNNABLE RUNNING!”);
}
};
public class MyCommand {
private Thread th;
private Runnable myRun;
public MyCommand(){
myRun = new Runnable() {
#Override
public void run() {
MyManager.getInstance().startTimeoutTimer();
try {
Thread.sleep(COMMAND_TIMEOUT_MILLIS * 3);
} catch (InterruptedException e) {}
MyCommand.this.execute();
}
};
th = new Thread(myRun);
}
public void execute() {
th.start();
mHandler.postDelayed(mTimeoutTimer);
}
}
private void startTimeoutTimer(){
mHandlerThread.start();
mHandler.postDelayed(mTimeoutTimer);
}
public void startCommand(){
new MyCommand().execute();
}
}
Also you forgot to start the mHandlerThread
private void startTimeoutTimer(){
mHandlerThread.start();
mHandler.postDelayed(mTimeoutTimer);
}
Related
I am new to Handler in Android, I wanna test Handler, so I use ThreadHandler and extends it, at the same time I override the method - run(), adding some log to indicate the start an end of the Looper. but when the test done, I just saw the start log and didn't see any end log, so why the override method run() didn't execute completely?
The code as following:
private void test_ThreadHandler(HandlerThreadTest handlerThreadTest){
handlerThreadTest.getHandler().post(new Runnable() {
#Override
public void run() {
Log.d(Tag, "handlerThreadTest quit!");
handlerThreadTest.quitSafely();
}
});
}
static class HandlerThreadTest extends android.os.HandlerThread {
private Handler mHandler;
public HandlerThreadTest(String name) {
super(name);
mHandler = new Handler();
}
public HandlerThreadTest(String name, int priority) {
super(name, priority);
mHandler = new Handler();
}
public Handler getHandler() {
return mHandler;
}
#Override
public synchronized void run() {
// I just see this log
Log.d(Tag, "Looper start!");
super.run();
// why I can't see this log ?
Log.d(Tag, "Looper end!");
}
}
Wrote an application to an Android to understand the control of view items from the child thread. Took the main looper from named Mainactivity and passed it through the constructor to a class that implements a child thread and that just changes the contents of TextView through callback.
public class MainActivity extends AppCompatActivity {
private TextView textView = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i("create", Thread.currentThread().toString());
textView = (TextView) findViewById(R.id.textView);
HandlerTextView handlerTextView = new HandlerTextView(getApplicationContext().getMainLooper());
handlerTextView.registerMessage(new Message() {
#Override
public void handleMessage(String msg) {
textView.setText(msg);
}
});
HandlerThread handlerThread = new HandlerThread("two", HandlerThread.NORM_PRIORITY);
if(handlerThread != null){
Handler a = new Handler(handlerThread.getLooper());
if(a != null) {
a.post(handlerTextView);
}
}
}
}
public class HandlerTextView implements Runnable {
private Looper mainLooper = null;
private TextView textView = null;
private Socket socket = null;
private Message message = null;
public HandlerTextView(Looper looper) {
this.mainLooper = looper;
}
public void registerMessage(Message m) {
this.message = m;
}
private void setText(final String str) {
Handler handler = new Handler(mainLooper);
handler.post(new Runnable() {
#Override
public void run() {
message.handleMessage(str);
}
});
}
#Override
public void run() {
setText("dfsdfsdfsdf");
}
}
Created a new Handlerthread thread handler object, took it looper
and passed it to the constructor of the new handler handler and it
The error: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity
ComponentInfo{elaneturn.com.myapplication/elaneturn.com.myapplication.MainActiv Caused by: java.lang.NullPointerException
Call handlerThread.start() before creating Handler:
handlerThread.start();
Handler a = new Handler(handlerThread.getLooper());
Hi my app needs a realtime data from database and I'm posting it on my TextView and I can't update the TextView as the database updates. I tried using Timer but its still the same.
Here is my code,
public void startTimer() {
//set a new Timer
timer = new Timer();
//initialize the TimerTask's job
initializeTimerTask();
timer.schedule(timerTask, 0, 5000);
}
private void stopTimerTask() {
//stop the timer, if it's not already null
if (timer != null) {
timer.cancel();
timer = null;
}
}
public void initializeTimerTask() {
timerTask = new TimerTask() {
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
final AcceptCars Cars = (AcceptCars) getIntent().getSerializableExtra("cars");
renterLat.setText(Cars.renterLat);
renterLng.setText(Cars.renterLng);
Log.d(TAG,renterLat.getText().toString());
Log.d(TAG,renterLng.getText().toString());
}
});
}
};
}
And here is where I get the Cars.renterLat and Cars.renterLng,
public class AcceptCars implements Serializable {
#SerializedName("renterLat")
public String renterLat;
#SerializedName("renterLng")
public String renterLng;
}
This is the logic you should be following. I used a Handler instead of a Timer. Inside the run method you need to call your webservice and get the updated value from the db. Use runOnUiThread to update the value to the UI from a Thread.
See the code below,
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Handler taskHandler = new Handler();
taskHandler.postDelayed(myTask, 0);
}
private Runnable myTask = new Runnable(){
public void run() {
queryDb();
// repeat the task
taskHandler.postDelayed(this, 1000);
}
};
private void queryDb(){
new Thread(new Runnable() {
#Override
public void run() {
// call you webservice
String data = callWebservice();
// parse the data in to AcceptCars pojo class
AcceptCars Cars = parseData(data);
//update the UI
runOnUiThread(new Runnable() {
#Override
public void run() {
renterLat.setText(Cars.renterLat);
renterLng.setText(Cars.renterLng);
}
});
}
}).start();
}
You can even use countdown timer.
Here is the link https://developer.android.com/reference/android/os/CountDownTimer.html
TimerTasks are really hard to deal with IMO. You should use a Handler and call postDelayed to do something after a certain amount of time.
Alternatively, you can try out this timer class I wrote:
import android.os.Handler;
public class Timer {
private Handler handler;
private boolean paused;
private int interval;
private Runnable task = new Runnable () {
#Override
public void run() {
if (!paused) {
runnable.run ();
Timer.this.handler.postDelayed (this, interval);
}
}
};
private Runnable runnable;
public int getInterval() {
return interval;
}
public void setInterval(int interval) {
this.interval = interval;
}
public void startTimer () {
paused = false;
handler.postDelayed (task, interval);
}
public void stopTimer () {
paused = true;
}
public Timer (Runnable runnable, int interval, boolean started) {
handler = new Handler ();
this.runnable = runnable;
this.interval = interval;
if (started)
startTimer ();
}
}
It is really simple to use.
You can use it like this:
Timer timer = new Timer(new Runnable() {
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
final AcceptCars Cars = (AcceptCars) getIntent().getSerializableExtra("cars");
renterLat.setText(Cars.renterLat);
renterLng.setText(Cars.renterLng);
Log.d(TAG,renterLat.getText().toString());
Log.d(TAG,renterLng.getText().toString());
}
}
}
}, 5000, true);
I have the below singleton handler class
public class MyHandler
{
private static Handler handler;
private static boolean isRunning;
public static Handler getHandler(Runnable myRunnable)
{
if (handler == null)
{
initHandler(myRunnable);
}
return handler;
}
private static void initHandler(Runnable myRunnable)
{
handler = new Handler();
isRunning = true;
handler.postDelayed(myRunnable, 5000);
}
public static void reRunHandler(Runnable myRunnable)
{
isRunning = true;
handler.postDelayed(myRunnable, 45000);
}
public static void stopMyHandler()
{
isRunning = false;
handler.removeCallbacksAndMessages(null);
}
}
However, how can I update my UI from here ? As the runnables are inside my activity. Apparently I cannot use getHandleMessage to communicate with it.
If you need more code, how am I using this, I can share.
It's very simple:
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
//do whatever you want on the UI thread
}
});
Handle has functions for this purposes:
private final Handler handler = new Handler() {
public void handleMessage(Message msg) {
// here you can get data from Message and update your UI. runs in UI thread
}
};
If you will send message with data to your Handler use next code:
Message m = new Message();
Bundle b = new Bundle();
b.putInt("myNumber", 5); // for example
m.setData(b);
myHandler.sendMessage(m);
i am trying to make facebook asynchronous non blocking thread in android. due to which our UI is run separate thread but i am unable to do that can any one tell me how to do that.
and If possible pleade give me one example.
Thanks.........
I don't know much about the Facebook but to access to the ui component from the other thread-
public class Dictionary extends Activity{
Handler mhandler;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Handler mhandler = new Handler();
SearchThread thread = new SearchThread();
thread.setParent(this);
thread.setHandler(mhandler);
}
public void notifyItemChanged(ArrayList<ListItem> lItems){
//write code relating to ui here
}
private class SearchThread extends Thread{
private Handler handler;
Dictionary parent;
public void setParent(Dictionary parent) {
this.parent = parent;
}
public void setHandler(Handler handler) {
this.handler = handler;
}
#Override
public void run() {
final Runnable mUpdateResults = new Runnable() {
public void run() {
parent.notifyItemChanged(listItems);
}
};
handler.post(mUpdateResults);
}
}