Executing a runnable argument in a custom thread class - java

I want to define my runnable in my main thread and then pass it as an argument into another thread like below -
final Runnable runnable = new Runnable() {
#Override
public void run() {
Log.i("Running runnable","");
}
};
Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
text.setText(msg.obj.toString());
}
};
ThreadTest handlerThreadTest = new ThreadTest(runnable, handler);
handlerThreadTest.start();
The ThreadTest class is defined as below -
public class ThreadTest extends Thread {
private Handler handler;
private Runnable runnable;
public ThreadTest(Runnable runnable, Handler handler) {
this.handler = handler;
this.runnable = runnable;
}
#Override
public void run() {
super.run();
runnable.run();
Message msg = handler.obtainMessage();
msg.obj = "YUSSSSSS!";
handler.sendMessage(msg);
} }
I'm able to send the "YUSSSSSS" message to my handler but runnable.run() does not seem to be working because I see nothing in logcat.
Where am I getting this wrong?

Logcat tends to erase empty messages, add some characters to your log and you may see something under the TAG of "Running runnable"
Log.i("RunnableImpl", "Running runnable");

Related

why handleMessage run in ui thread While I created handler with background thread looper?

why handleMessage run in ui thread while I created handler with background thread looper? this looper does not belong to the ui thread but alertdialog is shown correctly and without crashing, while an error should be given.
Excuse me if the question is not clear, because I do not know English well
public class ToastService extends Service {
private HandlerThread thread;
private Looper looper;
ServiceHandler handler;
public static int num=0;
int idd=0;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Log.i("say","created");
thread=new HandlerThread("mhm", Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
looper=thread.getLooper();
handler=new ServiceHandler(looper);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
int messageIntent=0;
if (intent!=null){
messageIntent=intent.getIntExtra("myMessage",0);
Log.i("sayonStartCommand",messageIntent+"");
}
Toast.makeText(this, "ook", Toast.LENGTH_SHORT).show();
Message message=new Message();
idd=messageIntent;
message.what=0;
message.arg1=startId;
Bundle bundle=new Bundle();
bundle.putInt("say",messageIntent);
message.setData(bundle);
handler.sendMessage(message);
return START_STICKY;
}
#Override
public void onDestroy() {
Log.i("say","finish xxxxxxxxxxxxxxxxxx");
super.onDestroy();
}
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
new AlertDialog.Builder(MainActivity.mcontext)
.setTitle("ok")
.setMessage("message").show();
int i=msg.getData().getInt("say");
Log.i("say",i+"");
if (idd==3){
stopSelf(msg.arg1);
}
}
}
}
looper=thread.getLooper(); this looper still runs on the main thread. So the Handler created with that looper also handles message in the main thread.
If you want to create a Handler that handles messages in the background thread.
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}

Synchronize handler thread

I am running a recursive handler which runs some code. I am posting the handler using a HandlerThread. I want to run the next recursive call only after the completion of the previous call.
Is it possible to do so? If not what are the alternatives.
HandlerThread ht = new HandlerThread();
ht.start();
Handler h = new Handler(ht.getLooper());
h.post(new Runnable() {
#override
public void run(){
//Some code
h.postDelay(this,1000);
}
});
Your code should work, but if you want a complete example how to run something recursively using HandlerThread, here it is:
public class Main2Activity extends AppCompatActivity {
private MyWorkerThread mWorkerThread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
mWorkerThread = new MyWorkerThread("myWorkerThread");
final Runnable task = new Runnable() {
#Override
public void run() {
Log.d("TAG", "Done.");
mWorkerThread.postTask(this);
}
};
mWorkerThread.start();
mWorkerThread.prepareHandler();
mWorkerThread.postTask(task);
}
#Override
protected void onDestroy() {
mWorkerThread.quit();
super.onDestroy();
}
}
class MyWorkerThread extends HandlerThread {
private Handler mWorkerHandler;
public MyWorkerThread(String name) {
super(name);
}
public void postTask(Runnable task){
mWorkerHandler.postDelayed(task, 1000); // set timeout which needed
}
public void prepareHandler(){
mWorkerHandler = new Handler(getLooper());
}
}
Don't forget to call handlerThread.quit() in onDestroy

it says that looper.prepare must be called

I am updating progress bar with the help of handler of MainActivity
but it gives the error :Can't create handler inside thread that has not called Looper.prepare()
Error
public class MainActivity extends AppCompatActivity {
ProgressBar progressBar;
Handler handler;
Thread thread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
thread = new Thread(new MyThread());
thread.start();
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
progressBar.setProgress(msg.arg1);
}
};
}
class MyThread implements Runnable {
#Override
public void run() {
Message message = Message.obtain();
for (int i = 0; i < 100; i++) {
message.arg1 = i;
handler.sendMessage(message);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
The error is because you are updating your UI from a different thread. So what you should be doing is like call the update method on main ui thread
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
runOnUiThread(new Runnable() {
#Override
public void run() {
// Do something on UiThread
// update progress
}
});
};
You should run progress bar only on Main Looper.
Add
handler = new Handler(context.getMainLooper()) {
.....
}
Should work.

Threading Android execute void in the UI thread

right now i'm doing
public void someStuff(){
new Thread(new Runnable() {
#Override
public void run() {
//doing long task
doOtherStuff();
}
}).start();
}
public void doOtherStuff(){
doEvenMoreStuff();
}
but the problem is that it executes doOtherStuff in the same thread and It needs to be executed in the UI Thread. how can I accomplish this?
I am only using the thread because otherwise the app freezes. I just need doOtherStuff to wait for the thread to finish.
Try this:
this.runOnUiThread(new Runnable() {
#Override
public void run() {
//do something
}
});
this is your activity.
Use handler :
public void doOtherStuff(){
new Handler(context.getMainLooper()).post(new Runnable() {
#Override
public void run() {
// Executes on UI thread
doEvenMoreStuff();
}
});
}
where context might be your Activity
Not sure if best practice but you can Try this:
public void someStuff(){
new Thread(new Runnable() {
#Override
public void run() {
YourActivityClassName.this.runOnUiThread(new Runnable() {
#Override
public void run() {
//doing long task
doOtherStuff();
}
});
}
}).start();
An alternative way of using Handler which other answers suggested is AsyncTask:
It has two methods which can be useful in your case:
doInBackground: which runs in the background thread so your UI won't freeze
onPostExecute: which runs on UI thread after doInBackground finishes. A generic class may look like:
private class MyTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... input) {
//do background processes on input and send response to onPostExecute
return response;
}
#Override
protected void onPostExecute(String result) {
//update UIs based on the result from doInBackground
}
}
and you can execute the task by:
new MyTask(inputs).execute()

Android Java object with own thread using looper

I have tried to implement object in Android that would work in its own thread (I do not want to make handler public, I want to wrap sentMessage method with own public api). It has public methods to pass data to object. This object is associated with activity lifecycle (onResume, onPause). I would like to use looper and handler, not just pure Java thread with infinite loop. I want to start worker thread on resume and stop working on pause callback. Object has to wait for new message infinitely.
This is my code below:
public class ThreadingObject {
private MyThread thread;
public ThreadingObject() {}
public void onResume() {
thread = new MyThread();
thread.startWorking();
}
public void onPause() {
thread.stopWorking();
}
public void setMessage(Object object) {
Message msg = new Message();
msg.obj = object;
thread.handler.sendMessage(msg);
}
protected void work(Object object) {
//Do something with object in own thread
}
private class MyThread extends Thread {
public Handler handler;
#Override
public void run() {
Looper.prepare();
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
ThreadingObject.this.work((String[]) msg.obj);
}
};
Looper.loop();
}
public void startWorking() {
start();
}
public void stopWorking() {
handler.getLooper().quit();
}
}
}
Is it correct implementation? I receive warning: "sending message to a handler on a dead thread". Is there any issue that I do not see?
It is my implementation:
public class ThreadingObject {
private HandlerThread thread;
private Handler handler;
private Handler.Callback handlerCallback = new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
work(msg.obj);
return true;
}
};
public ThreadingObject() {}
public void onResume() {
thread = new HandlerThread("SurfaceView HandlerThread");
thread.start();
handler = new Handler(thread.getLooper(), handlerCallback);
}
public void onPause() {
if(thread != null) {
thread.quit();
thread = null;
}
handler = null;
}
public void setMessage(Object object) {
Message msg = new Message();
msg.obj = object;
handler.sendMessage(msg);
}
protected void work(Object obj) {
//Working
}
}
In that run() method, if you need to re run or use loop, you need to add it by your self, ex.
and your error, is happen because you try to call the thread that already finish.
boolean aLoopLoopLoop = true;
Handler handler;
// this handler, you no need to declare it repeatedly, just declare it in onCreate() is enough
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
ThreadingObject.this.work((String[]) msg.obj);
}
};
// -----
#Override
public void run() {
Looper.prepare();
final Looper looper = Looper.myLooper();
while(aLoopLoopLoop) {
// write your code here
Looper.loop();
}
// after loop exit, quit loop
handler.postDelayed(new Runnable() {
#Override
public void run() {
looper.quit();
}
}, 3000);
}
// -----
public void stopWorking() {
aLoopLoopLoop = false;
}

Categories