【问题标题】:AsyncTask without callback interface没有回调接口的 AsyncTask
【发布时间】:2012-04-17 14:30:50
【问题描述】:

我正在尝试解决这个问题:我有一个从 AsyncTask 扩展的类,它执行一些 http 方法,如下所示:

    public class RESTManager extends AsyncTask<Object, Object, String>
{
    public RESTManager(String url, MethodTypes myMethod,ICallbackHandler hndl, String     restMethod)
    {
        initialize();
    }

    private String doGET()
    {
    }

    private String doPOST()
    {
    }

    @Override
    protected String doInBackground(Object... params)
    {

    }

    @Override
    protected void onPostExecute(String result)
    {
    }

}

所以,从 Activity 我做这个:

RESTManager webService = new WSManager(URL, MethodTypes.REGISTER, params, this, WSManager.GET_METHOD);
webService.execute();

然后activity在callbak方法中接收响应(因为activity实现了这个接口):

public void response(String response)
{
    // some process
}

这工作正常,但我的问题是我希望答案出现在对某个函数的同一次调用中,然后该函数调用 .execute 方法,例如。

// This is a new class
public class MyWebServices()
{
    public User getUser(int id)
    {
        User myUser;

        RESTManager webService = new WSManager(URL, MethodTypes.REGISTER, params, this, WSManager.GET_METHOD);
        webService.execute();

        // BUT I WANT TO RETURN FROM HERE THE CALL FROM THE ACTIVITY....LIKE

        return myUser;
    }
}

所以从活动来看,这将是:

MyWebServices myService = new MyWebServices();
User usr = myService.getUser(id);

希望不明白我试图描述的内容,谢谢!

【问题讨论】:

标签: java android callback android-asynctask


【解决方案1】:

您想要的会导致 UI 阻塞。 Android 不允许您这样做。网络调用应该是异步的,所以方法是错误的。处理response() 方法。

UPD:阻止用户界面会导致“应用程序无响应对话框”,这会惹恼用户。另外,如果网络调用失败怎么办?还是要等半个小时才能完成?

【讨论】:

  • 是的,我现在就是这样,并且同意。但是处理响应的正确方法是什么?例如使用开关(wsMethodExecuted)?因为每个方法都有不同的参数(字符串、用户对象、List 等),所以我必须切换 methodExecuted 并以正确的方式转换参数?
【解决方案2】:

学会爱上回调:)

您不能在不阻塞 UI 线程的情况下应用您提到的模式(在后台执行、等待结果、返回值)。

最简单的就是简单的实现onPostExecute()方法,在REST调用完成后调用你想做的事情。但是,如果您想向系统的其他部分公开一个干净的接口,您可以变得更复杂。

首先阅读observer pattern。可以这样想:REST 调用的完成是一个事件,对该事件感兴趣的代码可以注册以在它完成时(异步)得到通知。你可以这样做,我让你的 AsyncTask 像这样实现,

AsyncTask myTask = new AsyncTask<...>() {
    public interface Callback {
        void onComplete();
        void onFailure();
    }

    private Set<Callback> callbacks = new HashSet<Callback>();

    public void addObserver(Callback cb) { callbacks.add(cb); }

    @Override
    protected String doInBackground(Object... params)
    {
        // whatever
    }

    @Override
    protected void onPostExecute(String result)
    {
        if (success) {
            for (Callback cb: callbacks) {
                cb.onComplete();
            }
        } else {
            for (Callback cb: callbacks) {
                cb.onFailure();
            }       
        }
    }
}

现在,这个接口的消费者做了类似的事情,

MyTask mt = new MyTask();
mt.addObserver(new MyTask.Callback() { 
    @Override
    public void onComplete() {
        // do whatever you want to do when the task completes successfully
    }

    @Override
    public void onFailure() {
        // ...
    }
}

mt.execute();

【讨论】:

  • 好的,是的,我喜欢回调!只是有时我认为代码不清晰或不干净,但也许是我的看法。此外,我不确定如何在回调响应方法中实现代码,因为根据我调用的 REST 方法,结果(参数)会有所不同,请参阅我对 Vladimir 的分析器,谢谢!编辑:关于参数, onComplete() 的参数类型将是 Object 类型?然后根据 REST 方法调用将其转换为正确的类型?
  • 无论具体调用如何,REST 调用的结果都是相同的。也就是说,它有一个响应代码和一个正文。 onComplete() 可以将这些作为参数,允许调用者检查错误,如果成功,则处理正文结果。
  • 可能我表达的不是很好,在onPostexecute方法中,字符串参数是我从服务接收到的JSON字符串,所以我得把这个解析成我正确的对象(所以这里我必须知道我调用的服务是谁才能知道该服务的答案)然后我必须通过 onComplete 方法将此对象传递给调用该服务的活动
  • 好吧,有几个选项.. 1) 每种调用类型都有一个唯一的 AsyncTask,并为特定的响应对象类型提供一个内部回调。 2)让你所有的“响应”对象从一个公共基础扩展,并将其传递给你的回调方法或 3)让回调方法只接受一个字符串,并让调用者将它绑定到特定的响应对象类型。
猜你喜欢
  • 2020-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-06
  • 1970-01-01
  • 2017-07-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多