1

I refer this solution to run AsyncTask for multiple time. But I am getting following error when i call tryAgain.signal();

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.webapi_testing, PID: 3951
java.lang.IllegalMonitorStateException 
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signal(AbstractQueuedSynchronizer.java:1917)
at com.medimanage.webapi_testing.AsyncHttpRequest_Recursive.runAgain(AsyncHttpRequest_Recursive.java:156)
at com.medimanage.webapi_testing.AsyncHttpRequest_Recursive.onProgressUpdate(AsyncHttpRequest_Recursive.java:145)
at com.medimanage.webapi_testing.AsyncHttpRequest_Recursive.onProgressUpdate(AsyncHttpRequest_Recursive.java:17)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:648)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5052)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:796)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:612)
at dalvik.system.NativeStart.main(Native Method)

following is my asyncTask class;

public class AsyncHttpRequest extends AsyncTask<Void, String, String> {

    private String UrlString = "";
    private boolean _showProgressDialog = false;
    private ProgressDialog Dialog;
    private Context mContext;
    private IHttpRequestCompletedListener listener;
    private boolean isActivity = true;
    private String _messageText = "Please wait..."; 
    private String type = "get";
    private HttpUtility utility;

    private final ReentrantLock lock = new ReentrantLock();
    private final Condition tryAgain = lock.newCondition();
    private volatile boolean finished = false;
    boolean lockAcquired = false;

    public AsyncHttpRequest(String urlString, Context context, IHttpRequestCompletedListener listener, boolean _showProgressDialog) {
        UrlString = urlString;
        this._showProgressDialog = _showProgressDialog;
        this.mContext = context;
        this.listener = listener;
        Dialog = new ProgressDialog(this.mContext);
        this.utility = new HttpUtility(this.UrlString, mContext, listener);
    }

    public void addGetHeader(String headerData) {
        this.utility.addGetHeader(headerData);
    }

    public void setWaitMessage(String msgText) {
        if (!msgText.equals(""))
            msgText = "\n" + msgText;
        this._messageText = _messageText + msgText;
    }


    @Override
    protected void onPreExecute() {
        if (_showProgressDialog) {
            Dialog.setMessage(this._messageText);
            Dialog.setCancelable(false);
            Dialog.setCanceledOnTouchOutside(false);
            Dialog.show();
        }
    }

    @Override
    protected String doInBackground(Void... params) {
        try {
            String result = "";
            lock.lockInterruptibly();
            do {                
                if (!Utilities.isNetworkAvailable(mContext))
                    result = "No network available";
                else if (this.type.equals("get"))
                    result = utility.doGetRequest();
                else
                    result = utility.doPostRequest();
               
                publishProgress(result);
                tryAgain.await();

            } while (!finished);

            lock.unlock();
            return result;
        } catch (MediCorporateException tex) {            

            if (listener != null) {
                if (isActivity) {
                        ((Activity) mContext).runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                listener.OnHttpRequestError();
                            }
                        });
                    } 
                } else {                   
                        ((GcmIntentService) mContext).runOnUIThread(new Runnable() {
                            @Override
                            public void run() {
                                listener.OnHttpRequestError();
                            }
                        });
                    } 
                }
            }
            Utilities.callCrashReport(mContext, tex);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }finally {
            lock.unlock();
        }
        return "";
    }

    @Override
    protected void onProgressUpdate(String... values) {
        if (this.listener != null) {
            if(values.length > 0) {
                if (!Utilities.isNullOrEmpty(values[0])) {
                    listener.OnHttpRequestCompleted(values[0]);
                    terminateTask();
                } else {                   
                    runAgain();
                }
            }else {
                runAgain();
            }
        }
        Log.i("Exit ", "onProgressUpdate");
    }

    public void runAgain() {
        // Call this to request data from the server again
        tryAgain.signal();
    }

    public void terminateTask() {
        // The task will only finish when we call this method
        if (_showProgressDialog)
            this.Dialog.dismiss();
        finished = true;
        if(lock.isHeldByCurrentThread())
        {
            lock.unlock();
        }
    }

    @Override
    protected void onPostExecute(String Result) {      
        Log.i("Exit ", "onPostExecute");
    }
}

When I got empty response from WebService I called runAgain() and app gets crashed. Please give any solution to handle this exception.

Community
  • 1
  • 1
priyanka kamthe
  • 519
  • 2
  • 5
  • 19

1 Answers1

1

You should acquire a lock associated with the Condition before call signal.

public void runAgain() {
    // Call this to request data from the server again
    lock.lock();
    try {
        tryAgain.signal();
    } finally {
        lock.unlock();
    }
}

The solution You referenced has a own bug.

Below is copied from Android API Reference.

Implementation Considerations

An implementation may (and typically does) require that the current thread hold the lock associated with this Condition when this method is called. Implementations must document this precondition and any actions taken if the lock is not held. Typically, an exception such as IllegalMonitorStateException will be thrown.

If job should be executed multiple times, Thread, Handler or Service can be a better choice than AsyncTask.

You Kim
  • 2,355
  • 1
  • 10
  • 11