Android,我可以把AsyncTask放到一个单独的类中并使用回调吗?

17

我正在学习AsyncTask,并希望将其作为一个独立类来使用,而不是作为子类。

例如,

class inetloader extends AsyncTask<String, Void, String> {


    @Override
    protected String doInBackground(String... urls) {

        String response = "";

            DefaultHttpClient client = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(urls[0]);
            try {
                HttpResponse execute = client.execute(httpGet);
                InputStream content = execute.getEntity().getContent();

                BufferedReader buffer = new BufferedReader(
                        new InputStreamReader(content));
                String s = "";
                while ((s = buffer.readLine()) != null) {
                    response += s;
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

        return response;
    }


    @Override
    protected void onPostExecute(String result) {
        Log.e("xx",result);
        // how do I pass this result back to the thread, that created me?
    }


}

还有主(ui)线程:

inetloader il = new inetloader();
il.execute("http://www.google.com");
//il.onResult()
//{
    ///do something...
//}

谢谢!


1
是的,你可以把它放在一个单独的类中,但大多数人不这样做,因为如果它是一个内部类,它的目的通常更加清晰。如果你要在许多活动中重复使用它,请继续。 - keyser
我计划将它用于不同的目的,例如如果我从这里调用它,在结果上它应该做这个和那个,如果我从那里调用它,在结果上它应该做其他事情...因此,如果我将它保留在同一个类中,并在结果上从该类调用一个函数,我将不得不为它必须在结果上执行的每种操作创建一个新的AsyncTask... - Roger Travis
使用接口,只需通过接口实现您的活动,并在异步类的onPostExecute()中调用mContext.implementedMethod()。 - Anand Tiwari
将其放在一个单独的类中还有助于版本控制和变更管理。 - Kris Krause
1
顺便提一下,请使用大写字母开头来命名你的类,例如"InetLoader"——这只是基本的Java约定。 - Richard Le Mesurier
3个回答

34

使用一个接口。例如:

interface CallBackListener{
  public void callback();
}

那么在你的UI线程中执行以下操作:

inetloader il = new inetloader();
li.setListener(this);
il.execute("http://www.google.com");

在inetloader中添加:

   CallBackListener mListener;

   public void setListener(CallBackListener listener){
     mListener = listener;
   }

然后在 postExecute() 中执行:

   mListener.callback();

谢谢,听起来这是正确的方向。特别是如果我可以创建一个CallBackListener,使用inetloader il = new inetloader();并将其传递到il对象中。 - Roger Travis
嗯...奇怪,我在Android v3中没有找到“CallBackListener”,也许它有其他的名称? - Roger Travis
4
是的,你需要自己创建一个CallBackListener接口。别忘了在你的主UI类中添加“implements CallBackListener”的内容。 - Xi 张熹
哎呀,看起来它只为UI线程提供了一个@Override public void callback()。我是否有办法为我创建的每个inetloader对象制作多个callbacks(){}? - Roger Travis

3
您可以将活动实例传递给构造函数,并从那里调用活动函数... 就像使用接口:
public interface ResultUpdatable {

   public void setResult(Object obj);
   }

在Activity中实现此功能并将其传递给Async任务的构造函数,使用setResult函数从onPostExecute更新结果。


1
inetloader il = new inetloader();
il.execute("http://www.google.com");

String result = il.get();//put it in try-catch
                ^^^^^^^^ 

在这里,您将获得在onPostExecute(String result)中的结果


不是很好:(我需要一种onResult监听器,它会在AsyncTask完成后触发,因为查询某些服务器可能需要一段时间。另一方面,将il.get()放入while(true)循环中可能听起来太原始了,不是吗?:)有更好的选择吗? - Roger Travis
2
@Samir:这是一个非常糟糕的想法。虽然它确实允许从AsyncTask中检索结果,但使用get()方法将阻塞UI线程,有效地将应该是异步过程变成同步过程。我想到的唯一有效的get()方法用途是用于“链接”两个AsyncTasks - Squonk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接