Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handle response of WorkManager on Network connection Failure

I'm using WorkManager to sync data from my local Room database to server. The issue is that Room gives error to build database in Loop.MainLooper() and when i use it as following it works fine. But I'm unable to return the 'WorkerResult' on SUCCESS or RETRY based upon task completion. How to stop worker when Netwrok is lost?

public class TestSyncManager extends Worker {

    private final WorkerResult[] workerResult = {WorkerResult.SUCCESS};
    // @Inject            // Dagger2 has not added the support for dependency injection in worker yet.
    private ApiHeader mApiHeader;
    private HandlerThread mHandlerThread;
    private Handler mHandler;
    private Runnable mRunnable;
    private DataManager dataManager;

    @NonNull
    @Override
    public WorkerResult doWork() {
        try {
            //Looper.prepare();
                CommonUtils.Log("usm_work_manager_1", "Work is Started.");

                try {
                    checkNextCall();
                } catch (Exception e) {
                    e.printStackTrace();
                    setWorkerResult(WorkerResult.FAILURE);
                }
            };
            //mHandler = new Handler(Looper.myLooper());
            mHandlerThread = new HandlerThread("LikesHandlerThread");
            mHandlerThread.start();

            Looper looper = mHandlerThread.getLooper();
            mHandler = new Handler(looper);
            mHandler.post(mRunnable);
            //Looper.loop();


            return workerResult[0];
        } catch (Exception e) {
            e.printStackTrace();
            setWorkerResult(WorkerResult.FAILURE);
            return workerResult[0];
        }
    }

    private void checkNextCall() {
        List<LikeAction> likeActions = dataManager.getPendingLikeActions();
        CommonUtils.Log("usm_like_actions", "count= " + likeActions.size());
        if (likeActions.size() > 0) {
            LikeAction likeAction = likeActions.get(0);
            if (NetworkUtils.isNetworkConnected(getApplicationContext())) {
                dataManager.updateProcessingStatus(ActionType.LIKE_ACTION, likeAction.postId);
                requestLikesSync(likeAction);
            } else
                setWorkerResult(WorkerResult.RETRY);
        } else {
            setWorkerResult(WorkerResult.SUCCESS);
        }

    }

    @SuppressLint("CheckResult")
    private void requestLikesSync(LikeAction likeAction) {

                   /* int[] postIds = new int[likeActions.size()];
            for (int i = 0; i < likeActions.size(); i++) {
                postIds[i] = likeActions.get(i).postId;
            }*/
        LikeActionRemote.Request requestObj = new LikeActionRemote.Request(likeAction);

        String apiUrl = ApiEndPoint.BASE_URL + ApiEndPoint.LIKE_ACTION;

        try {
            LikeActionRemote.Response response = dataManager.doLikeActionApiCall(apiUrl, requestObj).blockingGet();
            Log.d("usm_response", "data= " + new Gson().toJson(response));
            if (response.isSuccess())
                dataManager.deleteProcessedActionById(ActionType.LIKE_ACTION, likeAction.postId);

            checkNextCall();
        } catch (Exception e) {
            e.printStackTrace();
        }
        CommonUtils.Log("usm_worker_network", "isNetworkConnected= " + NetworkUtils.isNetworkConnected(getApplicationContext()));
    }

    /**
     * This function will set the result of Worker and
     * it will clear Handler and will quit looper to let
     * the thread exit.
     *
     * @param result WorkResult (Success,Retry or Failure)
     */
    private void setWorkerResult(WorkerResult result) {

        workerResult[0] = result;
        if (mHandlerThread != null) {
            mHandlerThread.getLooper().quit();
            mHandlerThread.getLooper().getThread().interrupt();
            mHandlerThread = null;
            mHandler.getLooper().quit();
            mHandler.removeCallbacks(mRunnable);
            mHandler = null;
        }
    }
}
like image 724
Usman Rana Avatar asked May 29 '18 08:05

Usman Rana


1 Answers

instead of .subscribe use .blockingFirst() operator. If your api call fails, workManger will retry your request:

...
try{
    Response response = dataManager.doLikeActionApiCall(API.URL, requestObj).blockingFirst();
    if(response.isSuccess()){
        return WorkerResult.SUCCESS;
    }else{
        return WorkerResult.RETRY;
    }
}catch (NoSuchElementException|NullPointerException c){
        return WorkerResult.RETRY;       
}
like image 125
Lukas Avatar answered Oct 13 '22 15:10

Lukas