2013-04-05 101 views
2

我在API中使用AsyncTask來執行網絡操作。在UI部分有一個按鈕,點擊哪個觸發器API來執行請求/異步任務。 API正在實現從onPostExecute()方法更新的回調。 API會獲取正確的數據,onPostExecute()會將數據傳遞給回調函數。這一切都很好。但在更新到UI時,我遇到了一些概念性問題。這是我想要實現的: 1-點擊UI上的「Button」 2-我想更新API的響應字符串到UI。這是執行AsyncTask後得到的響應字符串。使用AsyncTask實現API並將結果更新到UI

問題是,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; 
} 
} 

Asy ncTask代碼

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

具有活性的實現:

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()。

+3

能否請您發佈一些代碼。它會讓我們更好地理解你想要達到的目標。我們將能夠以更好的方式幫助你。根據Shobhit說的 – 2013-04-05 02:00:07

+0

,需要代碼片段來更好地理解你。 – 2013-04-05 02:30:26

+0

將您的代碼發佈到asynctask並點擊按鈕 – 2013-04-05 02:30:37

回答

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

我希望保持UI代碼分離並希望通過API訪問服務器響應。上面的代碼需要從Asynctask代碼訪問UI組件,我試圖避免。 – bianca 2013-04-06 00:13:07

+0

看看我的修改答案。它使用Java線程而不是您正在使用的AsyncTask。當然,主要的區別在於這種方法不一定是異步的。但請注意:它可能會讓您的應用進入等待響應狀態,並被歸類爲不響應。 – DigCamara 2013-04-06 00:36:24

+0

感謝您的回答。在我看來,我認爲回調方法似乎更合適。感謝您花時間討論。 – bianca 2013-04-06 00:54:02