getLooper() returns null after started HandlerThread - android

I have an class extends HandlerThread, it looks like this:
public class MyHandlerThread extends HandlerThread {
private Object lock;
//constructor
public MyHandlerThread() {
super(“MyHandlerThread”);
lock = new Object();
}
public void prepare() {
//starts the handler thread
start();
//Wait for thread starting
Log.d(TAG, "wait for thread starting…");
synchronized (lock) {
try {
lock.wait(5000);
} catch (InterruptedException e) {
Log.e(TAG, "Failed to wait for thread to start");
}
}
//WHY getLooper() returns null here?
if(getLooper() == null) {
Log.d("GET LOOPER NULL!");
}
}
#Override
public void run() {
Log.d("run() begin...");
initializeSomeObjects()
Log.d(“initialise objects done!”);
//Notify that run() finished
synchronized (lock) {
lock.notify();
}
Log.d("run() end!”);
}
}
As you see above, the prepare() function starts the thread & wait for run() to be finished, then try to get looper.
In another class, I create an instance of MyHandlerThread & start it:
MyHandlerThread myThread = new MyHandlerThread();
myThread.prepare();
Logs showing in console:
wait for thread starting…
run() begin...
initialise objects done!
run() end!
GET LOOPER NULL!
Why in prepare() function, call to getLooper() returns null though the thread is already started (run() is executed)?

HandlerThread Looper is initialized in HandlerThread#run().
If you override the method and don't call super.run(), the init code from superclass is not executed.

Related

how to start first thread complete to after second thread start

Am using some method i need to some method complete to start to another method so that am using thread function, How to start one thread follow by to second thread start?
Thread thread1 = new Thread(new Runnable() {
#Override
public void run() {
try {
loadIrrigationSourceMaster();
loadIrrigationMaster();
loadSeasonMaster();
loadFactoryMaseter();
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread1.start();
Thread thread2 = new Thread(new Runnable() {
#Override
public void run() {
try {
loadTransport();
plantTypeMaster();
plotOwnerTypeMaster();
ExitRatoonMaster();
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread2.start();
(new Thread(new Runnable() {
#Override
public void run() {
//TODO: fist thread code here
Log.w("tag","1");
(new Thread(new Runnable() {
#Override
public void run() {
//TODO: second thread code here
Log.w("tag","2");
}
})).start();
}
})).start();
out put of above:
tag:1
tag:2
but i dont think it's a good idea . just put rest of your job in first Thread
To wait for a thread to complete its execution before moving on, you can use the join() method: docs
Specifically for your problem, you can put thread1.join(), right after the thread1.start() call. The join call will block the calling thread until thread1 is finished with its execution, so that thread2 will be initialized and executed after thread1 is finished.
Alternatively, you can also call thread1.join() in the beginning of the run() method of thread2, so that the main thread won't need to be blocked by the join() call.

HandlerThread throws RuntimeException Only one Looper may be created per thread

This crash report only contains system trace, because it happens in the HandlerThread:
java.lang.RuntimeException: Only one Looper may be created per thread
at android.os.Looper.prepare(Looper.java:107)
at android.os.Looper.prepare(Looper.java:102)
at android.os.HandlerThread.run(HandlerThread.java:54)
Seems the looper's prepare is called already for the HandlerThread.
I just don't understand why the HandlerThread's run entering again. It only shows the system's java stacktrace.
I tried calling the HandlerThread's start() method multiple times, it throwed java.lang.IllegalThreadStateException, not the RuntimeException.
So when HandlerThread throws such exception?
========================================================
The key code about the HandlerThread and Handler is below:
class MyDeviceFragment extends BaseFragment {
private HandlerThread mWorkerThread = new HandlerThread(MyDeviceFragment .class.getName());
private WorkerHandler mWorkerHandler;
{
if (mWorkerHandler == null) {
mWorkerThread.start();
mWorkerHandler = new WorkerHandler(mWorkerThread.getLooper());
}
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// xxxxx code
}
public void onDetach() {
super.onDetach();
if (mWorkerThread != null) {
mWorkerThread.quit();
}
}
private class WorkerHandler extends Handler {
WorkerHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MSG_XXXXX1:
synchronized (mLock) {
// CODE
}
break;
case MSG_XXXXX2:
synchronized (mLock) {
// CODE
}
break;
}
}
}
}
And using mWorkerHandler.sendEmptyMessage(MSG_XXX) to send message.
The initialization of mWorkerThread is a little weird, written by third-party, but I don't think it could cause HandlerThread throwing the RuntimeException. Am i right?
I think we can extends HandlerThread
#Override
public void run() {
try {
super.run();
} catch (Exception e) {
LogUtil.e(TAG, "run e =" + e);
}
}
But I have no idea about reason.

How to notify worker thread that UI is modified using Handler.Post()?

I have a worker thread and occasionally i send updates to the UI Thread using Handler.Post(). In some cases i need worker thread to wait until Handler.Post() executed on UI Thread and the view is modified and after UI thread is modified, notify the worker Thread to go on...
here is my simple worker thread:
workerThread = new Thread() {
#Override
public void run() {
progressBarHandler.post(new Runnable() {
public void run() {
//Step1: which works ok
ActionModeButton.performClick();
}
}
//Step2: returns null pointer exception because ActionMode
//is not yet created and R.id.select_recording is an
//ActionMode button if I put Thread.sleep(1000); here it
//will work fine.
final View selectRecording = getActivity()
.findViewById(R.id.select_recording);
selectRecording.post(new Runnable() {
public void run() {
selectRecording.performClick();
}
});
}
}
workerThread.start();
using synchronized block with wait and notify
final Handler handler = new Handler();
final Object lock = new Object();
new Thread(new Runnable() {
boolean completed = false;
#Override
public void run() {
handler.post(new Runnable() {
#Override
public void run() {
synchronized (lock) {
//Do some stuff on ui thread
completed = true;
lock.notifyAll();
}
}
});
synchronized (lock) {
try {
if(!completed)
lock.wait();
}
catch (InterruptedException e) {
}
}
}
}).start();
What about using a Semaphore for that?
Semaphore semaphore = new Semaphore(0);
uiHandler.post(new Runnable() {
// ... do something here
semaphore.release();
});
semaphore.acquire();
The Semaphore start with 0 permit. The thread will block on semaphore.acquire() until semaphore.release() (which will add a permit) is called.

How do I pass Runnable objects to a Handler?

I am learning via a book and it gives me this example:
Handler handler=new Handler() {
#Override
public void handleMessage(Message msg) {
bar.incrementProgressBy(5);
}
};
and
Thread background=new Thread(new Runnable() {
public void run() {
try {
for (int i=0;i<20 && isRunning.get();i++) {
Thread.sleep(500);
handler.sendMessage(handler.obtainMessage());
}
} catch (Throwable t) {
// just end the background thread
}
}
});
Which works out great. But, further down in the book it says:
If you would rather not fuss with Message objects, you can also pass
Runnable objects to the Handler, which will run those Runnable
objects on the activity UI thread. ...you can use those same methods
on any View (i.e., any widget or container). This slightly simplifies
your code, in that you can then skip the Handler object.
But there are no examples given of how to do this via a Runnable object. Does anyone have an example?
Something like this:
Handler h = new Handler();
Thread background=new Thread(new Runnable() {
public void run() {
try {
for (int i=0;i<20 && isRunning.get();i++) {
Thread.sleep(500);
handler.post(new Runnable() {
public void run() {
bar.incrementProgressBy(5);
}
});
}
}
catch (Throwable t) {
// just end the background thread
}
}
});
As per the Android Docs for Handler:
public final boolean post (Runnable r)
Since: API Level 1 Causes the Runnable r to be added to the message
queue. The runnable will be run on the thread to which this handler is
attached. Parameters
r -- The Runnable that will be executed. Returns
Returns true if the Runnable was successfully placed in to the message
queue. Returns false on failure, usually because the looper processing
the message queue is exiting.

How to start a new Thread in a service?

I am developing an Android app and I am doing some heavy work (bringing data from an online web page and parsing it to store in database) in a service. Currently, it is taking about 20+ mins and for this time my UI is stuck. I was thinking of using a thread in service so my UI doesn't get stuck but it is giving error. I am using the following code:
Thread thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
sleep(1000);
Toast.makeText(getBaseContext(), "Running Thread...", Toast.LENGTH_LONG).show();
}
} catch (InterruptedException e) {
Toast.makeText(getBaseContext(), e.toString(), Toast.LENGTH_LONG).show();
}
}
};
thread.start();
This simple code is giving run time error. Even If I take out the while loop, it is still not working.
Please, can any one tell me what mistake I am doing. Apparently, I copied this code directly from an e-book. It is suppose to work but its not.
Android commandment: thou shall not interact with UI objects from your own threads
Wrap your Toast Display into runOnUIThread(new Runnable() { });
Example of new thread creation taken from Android samples (android-8\SampleSyncAdapter\src\com\example\android\samplesync\client\NetworkUtilities.java):
public static Thread performOnBackgroundThread(final Runnable runnable) {
final Thread t = new Thread() {
#Override
public void run() {
try {
runnable.run();
} finally {
}
}
};
t.start();
return t;
}
runnable is the Runnable that contains your Network operations.
You can use HandlerThread and post to it, here is an example to service that has one.
public class NetworkService extends Service {
private HandlerThread mHandlerThread;
private Handler mHandler;
private final IBinder mBinder = new MyLocalBinder();
#Override
public void onCreate() {
super.onCreate();
mHandlerThread = new HandlerThread("LocalServiceThread");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
}
public void postRunnable(Runnable runnable) {
mHandler.post(runnable);
}
public class MyLocalBinder extends Binder {
public NetworkService getService() {
return NetworkService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
You may define your jobs in a runnable object, use a thread object for running it and start this thread in your service's onStartCommand() function. Here is my notes:
In your service class:
define your main loop in an Runnable object
create Thread object with the runnable object as parameter
In your service class's onStartCommand method():
call thread object's start function()
my code :
private Runnable busyLoop = new Runnable() {
public void run() {
int count = 1;
while(true) {
count ++;
try {
Thread.sleep(100);
} catch (Exception ex) {
;
}
ConvertService.running.sendNotification("busyLoop" + count);
}
}
};
public int onStartCommand(Intent intent, int flags, int startId) {
sendNotification("onStartCommand");
if (! t.isAlive()) {
t.start();
}
return START_STICKY;
}

Categories

Resources