Leucaruth
Leucaruth

Reputation: 43

Use Asynctask as a private class or with broadcast receiver?

I'm trying to make an application that uses Asynctask. Particularly, I want to make different http petitions with different JSON in different activities without the activity being frozen while the communication is done.

At first I thought to use asynctask as a private inner class in those activities, but I saw that they share a lot of code. So I thought to make a single class and play with broadcast receivers as I need to monitorize when I receive the result of the http petition, and isn't good to interfere with activity directly in the onPostExecute while in a different class.

What I want to know is, what is more efficient and better practice. Make a class that has the shared code and extends asynctask, then doing inner classes for each activity that extends that one or make a single asynctask that sends broadcast and receive them with each activity when needed.

Excuse my poor english, if needed I'll try to specify more clearly.

Thanks in advance

Upvotes: 1

Views: 809

Answers (3)

Ashish Vora
Ashish Vora

Reputation: 571

I have used Async task class as single class. And for every Webservice call i have used unique IntentFilter to Broadcast response. Put that Broadcast receiver in every class. You have perfect solution. Its working well.

Upvotes: 1

Tine M.
Tine M.

Reputation: 444

The way I found the best is just simply create public class that extends AsyncTask and then you just override onPostExecute function in every activity you use it.

Example:

MyDataTask dataTask = new MyDataTask() //you can add your parameters in class constructor
        {
            @Override
            protected void onPostExecute(Object result) //replace Object with your result type
            {
                MyActivity.this.doStuff(result); //use result in current activity
            }
        };

you can also create some custom functions to set private variables in datatask

dataTask.AddParam("user", username);
dataTask.AddParam("pass", pass);

and then just execute it with your args...

dataTask.execute(myArgs);

Upvotes: 1

Cat
Cat

Reputation: 67522

Background

What I want to know is, what is more efficient and better practice. Make a class that has the shared code and extends asynctask, then doing inner classes for each activity that extends that one or make a single asynctask that sends broadcast and receive them with each activity when needed.

I'm unclear as to why these are your only two options. Create a single AsyncTask, such as JsonPetitionTask, then push a new JsonPetitionTask.Data object. This object would contain your URL, your JSON, and any other data you need.

Setting up the AsyncTask

Something like this:

public class JsonPetitionTask extends AsyncTask<JsonPetitionTask.Data, Integer, Boolean> {
    protected Boolean doInBackground(JsonPetitionTask.Data... args) {
        for (int i = 0; i < args.length; i++) {
            JsonPetitionTask.Data data = args[i];
            // Send your JSON; check for errors, and return false if needed.
            if (isCancelled()) break;
        }
        return true;
    }

    protected void onProgressUpdate(Integer... progress) {
        // Show progress?
    }

    protected void onPostExecute(Boolean result) {
        // result is your success true/false.
    }

    public static class Data {
        public String jsonContent;
        public String petitionUrl;

        public Data(String content, String url) {
            jsonContent = content;
            petitionUrl = url;
        }
    }
}

Calling the JsonPetitionTask

Then you can call it like so:

JsonPetitionTask.Data data = new JsonPetitionTask.Data(myJSON, myURL);
new JsonPetitionTask().execute(data);

And voilà, you've executed your AsyncTask using only one class with no receivers.

Implementing a callback

Now, if you want to register a callback (something to execute that is specific to the calling code), that's a bit trickier. If this is part of what you're looking for, I'll be glad to edit this post and explain it.

To add a callback, we can use the Runnable class to execute some code after the job is done.

Firstly, we need to add a new field in the Data inner class:

public Runnable callback;

Next, before we call execute(), we need to add a new callback to our data object.

data.callback = new Runnable() {
    public void run() {
        // Whatever code you want to run on completion.
    }
};

Third, in the JsonPetitionTask class, we need a list of things to run:

private ArrayList<Runnable> mRunnables = new ArrayList<Runnable>();

Make sure, in each iteration of the doInBackground() loop, that you do mRunnables.add(data.callback);.

Lastly, in onPostExecute(), we need to call this:

protected void onPostExecute(Boolean result) {
    for (Runnable r : mRunnables)
        if (r != null) r.run();
}

I do realize I didn't send result to the Runnable, however I didn't feel like implementing a new Runnable type just to handle that. If you need this, I guess that's a bit of homework for you!

Upvotes: 1

Related Questions