-->

Handle response of WorkManager on Network connecti

2019-05-07 03:59发布

问题:

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;
        }
    }
}

回答1:

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;       
}