Reusing Async for Android Tasks

I am developing an application where, in a number of operations, I need to get data through Http. Once I have the data, I process it in the onPostExecute () callback method.

This works fine if I define the async task as an inline class, but since I want to do the same processing in several actions, I defined it as an external class.

So the question is that with the help of an external class I can pass the "event" back to the calling class as a means of transferring data back. I know how to do this in C #, but I'm new to Java and don't see how to do it.

+4
source share
5 answers

Although it is true that the listener is technically correct, I would say that it is too complex or not complex enough.

Here's a simpler solution:

class Foo { class Bar extends AsyncTask<Void, Void, Result> { public void onPostExecute(Result res) { doSomething(res); } } public void doSomething(Result res) { /// process result } public void startTask() { new Bar().execute(); } } 

It is equivalent to:

 class Bar extends AsyncTask<Void, Void, Result> { private final Foo foo; public Bar(Foo foo) { this.foo = foo; } public void onPostExecute(Result res) { foo.doSomething(res); } } class Foo { public void doSomething(Result res) { /// process result } public void startTask() { new Bar(this).execute(); } } 

... here's what you asked: when you pull out the inner class, you lose the implicit pointer. Just make it explicit and pass it on.

The bad news is that all sorts of memory leak and life cycle problems arise from this solution. I would recommend recommend that before your program gets even bigger, you learn to use IntentService instead of AsyncTask and use a handler or Activity.runOnUiThread to return the results to the user interface thread.

+4
source

One approach:

Define a parent abstract class called ParentActivity (extend action, of course). They have an abstract method called onAsyncCallback();

Each class that uses a task to extend this class and implement a method.

In its AsyncTask constructor, accept it in ParentActivity .

For instance,

 ParentActivity activity; public MyTask (ParentActivity myActivity) { this.activity = myActivity; } 

When done in onPostExecute() , just do

 activity.onAsyncCallback(data); 

This will also work with the interface, it does the same thing, except that you accept the constructor in the Listener instance.

+3
source

Use a listener template. See here TaskListener , Task using this listener and which invokes task

+1
source

Try creating your own HTTP class request that extends AsyncTask and then puts your code in a doInBackground call. Thyt you should only instantiate your class with url and params and read the answer. It worked for me.

Here is an example:

 public class HttpRequest extends AsyncTask<String, Void, String> { public String url; public List<NameValuePair> nameValuePairs; public String httpResponse =null; public HttpRequest(String _url, List<NameValuePair> _nameValuePairs) { url = _url; nameValuePairs=_nameValuePairs; } @Override protected String doInBackground(String... params) { httpResponse = getWebPageWithFormData(url, nameValuePairs); return ""; } public static String getWebPageWithFormData( String url, List<NameValuePair> nameValuePairs ){ String html = ""; HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost(url); if (nameValuePairs!=null){ try {httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));} catch (Exception e){} } HttpResponse response = null; try { response = httpclient.execute(httppost); } catch (ClientProtocolException e) { return ""; } catch (IOException e) { return ""; } int responseCode = response.getStatusLine().getStatusCode(); switch(responseCode) { case 200: HttpEntity entity = response.getEntity(); if(entity != null) { try{ html = EntityUtils.toString(entity);} catch (Exception e) {} } break; } return html; } } 
+1
source

If you want to do it in a clean way, try the following approach

First create an enumeration that contains all your asynchronous call names

 public enum TaskType { USER_LOGIN(1), GET_PRODUCTS(2), GET_EMPLOYEE(3); int value; private TaskType(int value) { this.value = value; } } 

Then create an interface

 public interface AsyncTaskListener { public void onTaskCompleted(String result, TaskType taskType); } 

Now we implement this interface in the activity that you are going to call GetAsyncTask for example: -

  public class LoginActivity extends Activity implements AsyncTaskListener { protected void onCreate(Bundle savedInstanceState) { String url = "....."; new GetAsyncTask(LoginActivity.this, LoginActivity.this, TaskType.USER_LOGIN).execute(url); } ... public void onTaskCompleted(String result, TaskType taskType) { if(taskType == TaskType.USER_LOGIN){ //your login result handling here } } 

Finally, this is your AsyncTask

 public class GetAsyncTask extends AsyncTask<String, Void, String> { String outputStr; ProgressDialog dialog; Context context; AsyncTaskListener taskListener; TaskType taskType; public GetAsyncTask(Context context, AsyncTaskListener taskListener, TaskType taskType){ this.context = context; this.taskListener = taskListener; this.taskType = taskType; } @Override protected void onPreExecute() { super.onPreExecute(); dialog = ProgressDialog.show(context, "Loading", "Please wait...", true); } @Override protected String doInBackground(String... params) { String urlString = params[0]; try { URL url = new URL(urlString); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); if (conn.getResponseCode() != 200) { throw new IOException(conn.getResponseMessage()); } // Buffer the result into a string BufferedReader rd = new BufferedReader( new InputStreamReader(conn.getInputStream())); StringBuilder sb = new StringBuilder(); String line; while ((line = rd.readLine()) != null) { sb.append(line); } rd.close(); conn.disconnect(); String jsonStr = sb.toString(); outputStr = jsonStr; } catch (SocketTimeoutException e) { outputStr = "timeout"; }catch(Exception e){ e.printStackTrace(); outputStr = "error"; } return outputStr; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); taskListener.onTaskCompleted(result, taskType); dialog.dismiss(); } } 
+1
source

All Articles