Android中AsyncTask的通用类?

Posted

技术标签:

【中文标题】Android中AsyncTask的通用类?【英文标题】:Common class for AsyncTask in Android? 【发布时间】:2011-03-18 12:23:27 【问题描述】:

我有一个通用类,例如 A 类,它扩展了 AsyncTask 并实现了所有方法,即 onPreExecutedoinbackgroundonPostExecute

现在,还有其他类想要使用 A 类对象。

说B类以下面的方式使用A类

A a = new A(context)
a.execute(url)

然后我在 get 方法中获取结果。但是 get 方法不是使用 AsyncTask 的正确方法。我想在onPostExecute 中得到结果。为此,我尝试使用布尔参数,该参数仅在onpostexecute 中为真。 B 类将检查直到它为真,当它为真时,它将获取结果。

但这会以某种方式阻止应用程序。

我已将 asynctask 的代码放在下面。

'

import java.io.IOException;

import org.apache.http.client.ClientProtocolException;

import org.apache.http.client.HttpClient;

import org.apache.http.client.ResponseHandler;

import org.apache.http.client.methods.HttpGet;

import org.apache.http.impl.client.BasicResponseHandler;

import org.apache.http.impl.client.DefaultHttpClient;


import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;

public class A extends AsyncTask<String, Void, String> 

private Context context = null;

private final HttpClient httpClient = new DefaultHttpClient();

private String content = null;
//private String error = null;
private String finalResult = null;
private static boolean isResult = false;

private ProgressDialog progressDialog = null; 

public BabbleVilleSyncTask(Context context)

    this.context = context; 
    progressDialog = new ProgressDialog(this.context);


protected void onPreExecute() 

    progressDialog.setMessage("Please Wait....");
    progressDialog.show();


protected String doInBackground(String... urls) 

    try 
    
        //urls[0] = URLEncoder.encode(urls[0], "UTF-8");

        HttpGet httpget = new HttpGet(urls[0]);
        ResponseHandler<String> responseHandler = new BasicResponseHandler();
        content = httpClient.execute(httpget, responseHandler);
    
    /*catch(UnsupportedEncodingException ue)
    
        error = ue.getMessage();
    */
    catch (ClientProtocolException e) 
    
        //error = e.getMessage();
        cancel(true);
    
    catch (IOException e) 
    
        //error = e.getMessage();
        cancel(true);
    

    httpClient.getConnectionManager().shutdown();

    return content;


protected void onPostExecute(String result) 

    finalResult = result;
    progressDialog.dismiss();
    System.out.println("on Post execute called");
    isResult = true;
  

public boolean getIsResult()

    return isResult;


public void setIsResult(boolean flag)

    isResult = flag;


public String getResult()

    return finalResult;


'

谁能告诉我可能是什么问题?

问候

苏尼尔

【问题讨论】:

【参考方案1】:

使用 AsyncTask 获取结果的一种简洁方法是使用回调接口。

下面是这个概念的一个简单例子:

interface AsyncTaskCompleteListener<T> 
   public void onTaskComplete(T result);

然后在你的 B 类:

class B implements AsyncTaskCompleteListener<String> 

    public void onTaskComplete(String result) 
        // do whatever you need
    

    public void launchTask(String url) 
        A a = new A(context, this);
        a.execute(url);
    

您现在应该将以下代码添加到您的 A 类中:

class A extends AsyncTask<String, Void, String> 
    private AsyncTaskCompleteListener<String> callback;

    public A(Context context, AsyncTaskCompleteListener<String> cb) 
        this.context = context;
        this.callback = cb;
    

    protected void onPostExecute(String result) 
       finalResult = result;
       progressDialog.dismiss();
       System.out.println("on Post execute called");
       callback.onTaskComplete(result);
     

这样,您不需要明确地等待任务完成,相反,您的主代码(可能是主 UI 线程)正在正常的 android 事件循环中等待,并且 onTaskComplete 方法将是自动调用,允许在那里处理任务结果。

【讨论】:

非常感谢。但是如果我想在一个执行方法中调用 3 个 url 怎么办。那么我们如何获取响应呢?任何想法 如果您从每个 url 的任务中调用 publishProgress,那么您有一个 onProgressMethod 方法应该可以很好地完成工作。 您能详细说明一下吗?我目前正在尝试转换此方法: public static int invokeWebServiceRequest(String uri, String username, String password, String targetKey);在扩展 AsyncTask 的类中。我将如何将这些参数(来自我的旧方法)传递给 doInBackground(Params ...)?谢谢! @SirDarius 帮助很大,谢谢。但这通常是 Android 中的一种很好的编码实践,还是将异步任务与 Activity 结合起来更好?我开始转向你提出的设计,但想问问你的想法是什么。我正在尝试使用更多 Activity -&gt; Helper -&gt; DTO -&gt; DAO -&gt; DB/Web service 模型,并且将 Async 任务从活动中移开当然更适用于该模型。感谢您的帮助 @wired00 这种方法不强制执行任何类型的耦合,但是请注意 AsyncTask.postExecute 方法将在主 UI 线程中执行,因此回调不能执行冗长的操作,可能降低用户体验。【参考方案2】:
public abstract class BaseTask<T> extends AsyncTask<Object, Void, T> 

    public Context context;
    public ProgressDialog dialog;
    public Exception exception;

    protected BaseTask() 
    

    public BaseTask(Context context) 
        this.context = context;
        this.dialog = new ProgressDialog(context);
    

    @Override
    protected void onPreExecute() 
        this.dialog.setMessage(context.getResources().getString(R.string.loading));
        this.dialog.show();
    

    @Override
    protected T doInBackground(Object... objects) 
        try 
           return doWork(objects);
         catch (Exception e) 
            exception = e;
        
        return null;
    

    @Override
    protected void onPostExecute(T result) 
        if (dialog.isShowing()) dialog.dismiss();
        if (exception == null) 
            onResult(result);
         else 
           onError();
        
    



    public abstract T doWork(Object... objects) throws Exception;
    public abstract void onResult(T result);
    public abstract void onError();




【讨论】:

【参考方案3】:

我会让 A 类成为嵌入在父类中的私有类,一旦完成工作,它应该更新父类属性,这在 PostExecute 上是可能的。

【讨论】:

是的,这是可能的。但我有 15-20 个活动,每个活动都有 http 连接。所以,这就是我为它创建一个单独的类的原因。但是现在m面临这个问题。那么,有什么方法可以从 onPostExecute 在其他类中获取结果。 如果您有 15 个以上的活动都使用 http 连接,您需要以某种方式对它们进行子类化,以便仅在您继承的 1 个超类中定义相同的功能。 请继续 - 因为我正在尝试为我的所有 http 请求创建一个类/单例 - 这不会中断主/UI 线程。 您需要在新问题中再次弹出问题。 @Pentium10 这是我目前正在做的,我肯定会在我的下一个项目中放弃这个方法。幸好我的很小。只是为了评论......

以上是关于Android中AsyncTask的通用类?的主要内容,如果未能解决你的问题,请参考以下文章

Android中的AsyncTask和接口回调使用详解

如何为 Android Room 请求制作通用 AsyncTask

AsyncTask Android - 设计模式和返回值

android中asynctask和thread的区别

android asynctask怎么用

Android O:AsyncTask分析