Question

I'm trying to get to grips with using callbacks in AsyncTasks because it seems to be the standard on how to update from a task... Issue is that I can't seem to get it to work, because resources online seem to be saying "do this and it'll work" as opposed to talking through it.

I'm going to talk through what I have, and if somebody could tell me where I'm going wrong/what exactly I should do, I'd appreciate it.

I have an interface called OnTaskCompleted in it's own file:

OnTaskCompleted:

package com.example;

public interface OnTaskCompleted{
    void onTaskCompleted(boolean result);
}

I then have another task containing some methods, and my AsyncTask:

ConnectUtils:

public class ConnectUtils implements OnTaskCompleted {

    private boolean hasConnected, hasChecked;

    public boolean isConnected(Context parent, String url){ 
        hasChecked = false;
        new CheckURL(parent, new OnTaskCompleted(){
            @Override
            public void onTaskCompleted(boolean result) {
                // TODO Auto-generated method stub

            }}, url).execute();
        while(!hasChecked){ Log.i("Checked?", hasChecked + ""); }
        return hasConnected;
    }

    private class CheckURL extends AsyncTask<Void, Void, Boolean>{

        private Context parent;
        private OnTaskCompleted listener;
        private String url;

        public CheckURL(Context parent, OnTaskCompleted listener, String url){
            this.parent = parent;
            this.listener = listener;
            this.url = url;
        }

        @Override
        protected Boolean doInBackground(Void... params){
            // Do some stuff and return a boolean
        }

        @Override
        protected void onPostExecute(Boolean result){
            super.onPostExecute(result);
            listener.onTaskCompleted(result);
        }
    }


    @Override
    public void onTaskCompleted(boolean result) {
        Log.i("Completed", result + "");
        hasConnected = result;
        hasChecked = true;
    }
}

What I'm expecting to see is that the while in isConnected() runs whilst we have no result from the AsynTask, and that once the Task is finished hasChecked sets to true and then stops the while loop.

What I'm seeing though, is that the loop continues infinitely and just logs false constantly, so hasChecked isn't being updated.

Can anyone explain where and why I might be going wrong?

I should probably note I'm more interested in how the callbacks work in general rather than inside this code (although use this code to explain). This is just example code.

Was it helpful?

Solution

The point of using AsyncTasks is to release the UI thread to other activities while some processing gets done on a non-UI thread in the AsyncTask.

However, in your code the UI thread (which gets priority) is locked into the while() loop waiting for a non-UI thread (which wont get priority) to complete the AsyncTask.

A better approach would be a different flow. First, initiate the connection:

public void ensureConnected(Context parent, String url){ 
    new CheckURL(parent, new OnTaskCompleted(){
        @Override
        public void onTaskCompleted(boolean result) {
            isChecked   = true;
            isConnected = result;

            // Change of state actions called from here
        }}, url).execute();
}

And in the AsyncTask:

private class CheckURL extends AsyncTask<Void, Void, Boolean>{
    private Context parent;
    private OnTaskCompleted listener;
    private String url;

    public CheckURL(Context parent, OnTaskCompleted listener, String url){
        this.parent = parent;
        this.listener = listener;
        this.url = url;
    }

    @Override
    protected Boolean doInBackground(Void... params){
        // Do some stuff and return a boolean
    }

    @Override
    protected void onPostExecute(Boolean result){
        super.onPostExecute(result);
        listener.onTaskCompleted(result);
    }
}

Finally, I'm not sure why you need an Interface here at all: you could do away with it entirely (as far as this simple example code goes) and set the state variables and trigger state change actions directly in onPostExecute.

OTHER TIPS

This is how the asynctask callback works

  1. First onPreExecute() is called which effectively runs on UI thread so you can do some UI activity here before the thread starts. For example you can start progress dialog here.

  2. Then doInBackgound() is called where the thread work is done in the background. You can publish intemediate results to UI thread by calling a function publishProgress(int) with the intermediate values.

  3. The intermediate valuse are posted to UI thread from onPublishProgress().

  4. The return of doInBackground() is finally taken by onPostExecute(). This callback again effectivly runs on UI thread and does the final work for UI thread based on asysntask result.

For details you can check the link below:

http://developer.android.com/reference/android/os/AsyncTask.html

Hope this helps you

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top