【问题标题】:Using AsyncTask to implement API and updating result to UI使用 AsyncTask 实现 API 并将结果更新到 UI
【发布时间】:2013-04-05 01:46:09
【问题描述】:

我在 API 中使用 AsyncTask 来执行网络操作。在 UI 部分有一个按钮,点击它会触发 API 来执行请求/异步任务。 API 正在实现从 onPostExecute() 方法更新的回调。一旦 onPostExecute() 将数据传递给回调,API 就会获取正确的数据。这一切都很好。但是我在更新到 UI 时遇到了一些概念问题。这就是我想要实现的目标: 1-单击用户界面上的“按钮” 2- 我想将 API 的响应字符串更新到 UI。我在执行 AsyncTask 后得到的这个响应字符串。

问题是 API 在当前执行线程中总是返回 null 作为响应。一旦 UI 线程完成,我就会看到 API/AsyncTask 数据进来。我知道我遗漏了一些非常微不足道但很重要的东西。你知道在 UI 上更新 API 响应的正确方法是什么吗?

[更新]

这是我的 UI 代码,其中包括通过 API 触发异步任务的单击按钮(只是另一个实现回调以获取服务器响应的类)

button.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {
                            API api = new API();
            Request request = new Request();
                    request.setUrl("http://www.example.com/");
                    api.fetch(request);

            try {
//It doesn't matter how much you wait here to return the response. 
//Response from task doesn't return in this thread. 
//If I click another button say "refresh" to refresh the data, then api.getResponseString() shows the response from server.
                Thread.sleep(2000);
//api.getResponseString() returns null. I expect it to return data just retrieved from server
                String text = api.getResponseString();
                System.out.println("Text: " + text);
                textView.setText(text);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    });

API 代码

public class Api implements ResponseCallbacks {

String responseString = null;

public void fetch(Request request) {
    makeRequest(request, this);
}

public void makeRequest(Request request,
        final ResponseCallbacks responseCallbacks) {
    MyTask asyncTask = new MyTask();
    asyncTask.setResponseCallbacks(responseCallbacks);
    asyncTask.execute(request);
}

@Override
public void onSuccess(Response response) throws IOException {
    if (response.isSuccess()) {
        responseString = "Success";
    } else {
        responseString = "Failed";
    }
}

public String getResponseString() {
    return responseString;
}
}

异步任务代码

public class MyTask extends AsyncTask {
private ResponseCallbacks responseCallbacks;

public MyTask() {}

public void setResponseCallbacks(ResponseCallbacks callbacks) {
    this.responseCallbacks = callbacks;
}

@Override
protected Response doInBackground(Request... params) {
    Request request = params[0];
    Response Response = null;

    try {
        //Make Http call and gets response from remote server here...
    } catch (Exception e) {

    }

    return response;
}

protected void onPostExecute(Response response) {
    if (response.isSuccess()) {
        try {
            if (response.isSuccess()) {
                callbacks.onSuccess(response);
            }
        } catch (Exception e) {
            callbacks.onFailure(response);
        }
    }
}


}

我想要的是在我点击按钮后在 textView 中更新从服务器返回的文本。

[更新 2] 显然,我发现如果我再定义一个回调,比如 UICallback 并让我的活动注册它,就可以解决问题。

UICallback:

public interface UICallback {
public void onFailure(String response);
void onSuccess(String response) throws IOException;
}

让 Activity 实现它:

public class MainActivity extends Activity implements UICallback {
    .......
    api = new NetApi();
api.setUICallbacks(this);
    .......

    @Override
public void onSuccess(String response) throws IOException {
    String text = api.getResponseString();
//works !
    textView.setText(text);

}
}

还有比这更好的解决方案吗?我真的不喜欢 Activity 实现额外回调的想法。如果我的 api 本身可以通过 api.getResponseString() 完成获取数据后提供服务器响应,那就太棒了。

【问题讨论】:

  • 能否请您发布一些代码。这将使我们更好地了解您想要实现的目标。我们将能够以更好的方式帮助您。
  • 正如 Shobhit 所说,需要代码 sn-p 才能更好地理解您。
  • 在异步任务中发布您的代码并单击按钮

标签: android android-asynctask


【解决方案1】:

我的猜测是,您正在寻找的实际上是runOnUIThread

如果您在onPostExecute 中使用它,您可以刷新您的 UI 数据,而无需注册回调等。像这样:

protected void onPostExecute(Response response) {
  if (response.isSuccess()) {
    try {
        if (response.isSuccess()) {

             runOnUiThread(new Runnable() {
                public void run() {
                    textView.setText(text);

                }
            });
        }
    } catch (Exception e) {
        callbacks.onFailure(response);
    }
  }
}

同步替代方案是在主线程中使用 Runnable。您必须立即重新定义 MyTask 以实现 Runnablejoin。像这样

Thread asyncTask = new Thread(MyTask());
asyncTask.start();
asyncTask.join();//gets called as soon as the task ends

MyTask 是

public class MyTask implements Runnable{

     public void run(){
         //do whatever you need to do
     }
}

【讨论】:

  • 我想保持 UI 代码分离并希望通过 API 访问服务器响应。上面的代码需要从 Asynctask 代码访问 UI 组件,而这正是我试图避免的。
  • 看看我修改后的答案。它使用 java Threads 而不是您使用的 AsyncTask。当然,主要区别在于此方法不一定是异步的。不过要小心:它可能会使您的应用进入等待响应并被归类为无响应的状态。
  • 感谢您的回答。到目前为止,我认为回调方法在我的情况下似乎更合适。感谢您抽出宝贵时间参与讨论。
  • 不客气!郑重声明,我同意:在这种情况下,启动和等待线程加入可能只会让您的应用无响应。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-04
相关资源
最近更新 更多