I am trying to implement a WorkManager
for a periodic background operation. I'm getting a common error when trying to use a Handler
in the Worker
. I know the error is saying I need to call Looper.prepare()
because I'm on the wrong thread but I'm not sure how to.
This is the code I'm using:
public class SyncWorker extends Worker {
private static TimeOutHandler mTimeOutHandler;
public SyncWorker(@NonNull Context context, @NonNull WorkerParameters params) {
super(context, params);
mTimeOutHandler = new TimeOutHandler(this);
}
@Override
public Result doWork() {
return Result.success();
}
private static class TimeOutHandler extends Handler {
private final WeakReference<SyncWorker> mMainWeakReference;
//this is where the error is thrown
TimeOutHandler(final SyncWorker service) {
mMainWeakReference = new WeakReference<>(service);
}
@Override
public void handleMessage(final Message msg) {
final SyncWorker service = mMainWeakReference.get();
if (service != null) {
switch (msg.what) {
case MESSAGE_CONNECTIVITY_TIMEOUT:
mTimeOutHandler.removeMessages(MESSAGE_CONNECTIVITY_TIMEOUT);
break;
}
}
}
}
}
Handler handler = new Handler(Looper.getMainLooper());
I've done some research and one suggested solution is to use:
Handler handler = new Handler(Looper.getMainLooper());
but I don't know how to do that with the way I'm extending Handler
.
When You've created constructor extending Handler
class, and you've added parameters for your constructor there are several ways to provide Looper
to your Handler
like below suggested approach.
You can create another constructor that access Looper
also:
TimeOutHandler(final SyncWorker service, Looper looper) {
super(looper);
mMainWeakReference = new WeakReference<>(service);
}
And initialize like :
TimeOutHandler handler = new TimeOutHandler(service, Looper.getMainLooper());
Directly passing Looper
to primary constructor:
TimeOutHandler(final SyncWorker service) {
super(Looper.getMainLooper());
mMainWeakReference = new WeakReference<>(service);
}
So calling super() initialize constructor of parent (super) class & in our case, we pass Looper
as parameter to super will initialize Handler with constructor Handler(Looper looper)
which previously was Handler()
(Empty or default constructor).
Note: The thing is Handler class has multiple constructors from which one accepts Looper
which is provided to switch Handler
to specific thread provided.