2013-01-21 133 views
4

我正在开发一个应用程序,其中在我需要通过Http检索数据的许多活动中。 一旦我有数据,我在onPostExecute()回调方法中处理它。Android异步任务重用

这很好,如果我将async任务定义为内联类,但是因为我想在一些活动中做同样的处理,所以我将它定义为外部类。

所以问题是,使用外部类如何将“事件”返回给调用类作为传递数据的手段。我知道如何在C#中做到这一点,但我是Java新手,无法看到如何实现这一点。

回答

4

虽然听众在技术上是正确的,但我会声称它太复杂或不够复杂。

这里有一个简单的解决方案:

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(); 
    } 
} 

等同于:

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(); 
    } 
} 

...是你问这是什么:当你拉内部类了,你失去了隐式指针。只需将其明确并通过即可。

坏消息是存在各种由此解决方案引起的内存泄漏和生命周期问题。我会非常多建议,在您的程序变得更大之前,您正在考虑使用IntentService而不是AsyncTask,并使用Handler或Activity.runOnUiThread将结果返回到UI线程。

+0

它可能会出现什么样的内存泄漏问题?你可以给一些关于如何使用IntentService而不是AysncTask的参考吗?我读了这个http://stackoverflow.com/questions/6343166/android-os-networkonmainthreadexception,强烈建议在http请求中使用'AsyncTask()'。 – Stallman

+0

我强烈反对6343166. AsyncTask问题的描述需要超过600个字符。只是谷歌为“AsyncTask内存泄漏”找到几十篇文章。有关如何使用IntentService的示例,请从eclipse/ADT中选择New> Other,然后在对话框中选择Android> Android Object> Next,然后选择Service(Intent Service)。你会得到一个很好的原型 –

+0

http://stackoverflow.com/questions/25345087/intentservice-connected-to-server-listening建议不要使用'intent service' – Stallman

3

一种方法:

定义名为ParentActivity父抽象类(延伸当然活性)。是否包含抽象方法onAsyncCallback();

让每个使用该任务的类都扩展该类并实现该方法。

在您的AsyncTask构造函数中,让它接受ParentActivity

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

onPostExecute()做,根本就

activity.onAsyncCallback(data); 

这也与接口工作,它做同样的事情,除了这一翻译你的构造在听者接受实例。

1

尝试制作自己的http请求类,以扩展AsyncTask并将其放在“doInBackground”调用中。你的方式你只需要使用url和params来实例化你的类并阅读响应。这对我有效。

这里是例子:

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

如果你想要做一个干净的方式尝试以下方法

首先创建一个包含所有的异步调用的名称枚举

public enum TaskType { 
    USER_LOGIN(1), GET_PRODUCTS(2), GET_EMPLOYEE(3); 

    int value; 

    private TaskType(int value) { 
     this.value = value; 
    } 
} 

然后创建一个界面

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

现在实施的活动这个界面,你要叫GetAsyncTask 如: -

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 
     } 
} 

最后,这是你的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(); 
    } 

}