user99999
user99999

Reputation: 2024

Use response from the AsyncTask as callback

I want to be able to call a method inside the onPostExecute() that exists in the class I invoke the asynctask from - how can I do that?

I mean, when I call the AsyncTask:

public class MainActivity extends AppCompatActivity {

    public function onButtonClick() {
        String url = "http://sampledomain.pl/test.php";
        String params = "";
        new Api().execute(url, params);
    }

    public function changeText(String response)
    { 
        TextView txt = (TextView) findViewById(R.id.text);
        txt.setText(response);
    }

}

I want to be able to call the changeText method from the onPostExecute method like this:

public class Api extends AsyncTask<String, Void, String> {
    // ...
    @Override
    public void onPostExecute(String response)
    {
        MainActivity obj = new MainActivity();
        obj.changeText(response);
    }

}

Two problems I see here:

  1. It doesn't work, I keep getting the java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.Window.findViewById(int)' on a null object reference error

  2. I want this class to be more generic, which means I want to specify the method I want to execute inside MainActivity class, not Api class.

How can I solve this?

Upvotes: 1

Views: 272

Answers (2)

Mateusz Korwel
Mateusz Korwel

Reputation: 1148

First you should create a callback interface. The code is generic and you can use it in other place in application.

public interface Callback<T>{
    void execute(T result);
}

Then you have to modify your AsyncTask, so as to accept Callback as a parameter in the constructor.

public class Api extends AsyncTask<String, Void, String> {
    public final Callback<String> callback;

    public Api(Callback callback) {
        this.callback = callback;
    }

    // other methods ...

    @Override
    public void onPostExecute(String response) {
        callback.execute(response);
    }
}

And then you can put callback in your AsyncTask.

public void onButtonClick() {
    String url = "http://sampledomain.pl/test.php";
    String params = "";
    new Api(new Callback<String>() {
        @Override
        public void execute(String result) {
            changeText(result);
        }
    }).execute(url, params);
}

Upvotes: 1

hack_on
hack_on

Reputation: 2520

Here is a possible interpretation of what you want to do. Pass a reference to the activity to the AsyncTask and also an enum value that specifies which method you want to call. Be careful that the context is different when these methods are executed in MainActivity from AsyncTask -- they are not on the UI thread.

public class MainActivity extends AppCompatActivity {

    ...

    doSomething(String response, MethodEnum method) {
        switch (method) {

            case ChangeText: changeText(response); break;

            case SomethingElse: somethingElse(response); break;

        }
    }
}

public class Api extends AsyncTask<String, Void, String, MainActivity, MethodEnum> {
    // ...
    // Main Activity is passed into doInBackground and set to a member 
    // variable there (mainAct), as is MethodEnum (method)

    @Override
    public void onPostExecute(String response) {
        mainAct.doSomething(response, method);
    }

}

Upvotes: 0

Related Questions