2013-04-05 4 views
2

Я использую AsyncTask в API для выполнения сетевых операций. В части пользовательского интерфейса есть кнопка, нажимающая на какой триггер API для выполнения задачи request/async. API выполняет обратный вызов, который обновляется из метода onPostExecute(). API получает нужные данные за один раз, когда onPostExecute() передает данные для обратного вызова. Все это работает хорошо. Но я получаю некоторые концептуальные проблемы при обновлении пользовательского интерфейса. Этого я хочу достичь: 1- Нажмите «Кнопка» в UI 2- Я хочу обновить строку ответа API для интерфейса. Эта строка ответа, которую я получаю после выполнения AsyncTask.Использование AsyncTask для реализации API и обновления результата для UI

Проблема в том, что API всегда возвращает null как ответ в текущем потоке выполнения. Как только поток пользовательского интерфейса выполняется, я вижу данные API/AsyncTask. Я знаю, что мне не хватает чего-то очень тривиального, но важного. Вы знаете, какой правильный способ обновить ответ API в пользовательском интерфейсе?

[Update]

Вот мой код 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 после я нажимаю кнопку.

[Update 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

Можете ли вы опубликовать код. Это даст нам лучшее понимание того, чего вы пытаетесь достичь. Мы сможем помочь вам лучше. –

+0

как сказал Шобхит, нужен фрагмент кода, чтобы лучше понять вас. –

+0

Опубликуйте свой код в asynctask & button нажмите –

ответ

1

Я предполагаю, что вы ищите на самом деле runOnUIThread.

Если вы используете это в onPostExecute, вы можете обновить данные своего пользовательского интерфейса без регистрации обратных вызовов и еще чего-то. Например:

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 для реализации Runnable и join сразу после.Как это

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

Я хочу, чтобы код пользовательского интерфейса был разделен и вы хотите получить ответ сервера через API. Для кода выше необходим компонент пользовательского интерфейса, доступ к которому можно получить из кода Asynctask, и именно этого я пытаюсь избежать. – bianca

+0

Посмотрите на мой исправленный ответ. Он использует java Threads вместо используемой вами AsyncTask. Главное различие, конечно, в том, что этот метод не обязательно асинхронен. Однако осторожно: это может привести ваше приложение в состояние, в котором он ждет ответа и классифицируется как невосприимчивый. – DigCamara

+0

спасибо за ваш ответ. Я думаю, что метод обратного вызова представляется более подходящим до сих пор в моем случае. Спасибо, что нашли время в обсуждении. – bianca

Смежные вопросы