Подтвердить что ты не робот

Как получить строку из AsyncTask?

У меня есть следующий класс:

public class getURLData extends AsyncTask<String, Integer, String>{

@Override
protected String doInBackground(String... params) {
    String line;
    try {  
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(params[0]);

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        line = EntityUtils.toString(httpEntity);

    } catch (UnsupportedEncodingException e) {
        line = "<results status=\"error\"><msg>Can't connect to server</msg></results>";
    } catch (MalformedURLException e) {
        line = "<results status=\"error\"><msg>Can't connect to server</msg></results>";
    } catch (IOException e) {
        line = "<results status=\"error\"><msg>Can't connect to server</msg></results>";
    }
    return line;
}

@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
}

}

И я пытаюсь назвать это следующим образом:

String output = null;
output = new getURLData().execute("http://www.domain.com/call.php?locationSearched=" + locationSearched);

Но выходная переменная не получает данные, вместо этого я получаю сообщение об ошибке:

Type mismatch: cannot convert from AsyncTask<String,Integer,String> to String
4b9b3361

Ответ 1

Метод execute возвращает сам AynscTask, вам нужно вызвать get:

output =
    new getURLData()
        .execute("http://www.example.com/call.php?locationSearched=" + locationSearched)
        .get();

Это запустит новый поток (через execute), блокируя текущий поток (через get), пока работа из нового потока не будет завершена, и результат будет возвращен.

Если вы это сделаете, вы просто превратили свою задачу async в синхронизацию.

Однако проблема с использованием get заключается в том, что, поскольку она блокирует, ее нужно вызвать в рабочем потоке. Тем не менее, AsyncTask.execute() необходимо вызвать в основном потоке. Поэтому, хотя этот код может работать, вы можете получить некоторые нежелательные результаты. Я также подозреваю, что get() недостаточно проверен Google, и возможно, что они ввели ошибку где-то вдоль линии.

Ссылка: AsyncTask.get

Ответ 2

Я бы предпочел создать обратный вызов, чем поток блоков UI. В вашем классе создайте метод, который будет вызываться при поступлении данных. Например:

private void setData(String data){
    mTextView.setText(data);
}

Затем в реализации AsyncTask onPostExecute:

@Override
protected void onPostExecute(String result) {
    setData(result);
}

А потом где-то в коде просто выполните задачу:

new getURLData().execute(...

Когда задача заканчивается, запускается setData и заполняется mTextView.

AsyncTask.get() будет блокировать ваш пользовательский интерфейс, поэтому нет смысла использовать AsyncTask.

Ответ 3

Если пользователь нажимает кнопку, то должен ждать содержимого, что они делают тем временем?

Почему бы не сделать это:

  • Пользователь нажимает кнопку.
  • Вы проверяете возможность подключения. Если пользователь не подключен к Интернету, сообщите им.
  • Вы запускаете IntentService, отправив Intent для отправки HTTP-запроса.
  • Когда запрос завершается, вы отправляете уведомление.
  • Пользователь нажимает уведомление, которое возвращает в действие, которое может сделать следующий шаг.

Это позволяет пользователю отключиться и делать что угодно во время обработки запроса.

IntentService работает в фоновом режиме в своем потоке. Когда он получает намерение, он запускается onHandleIntent(). Когда этот метод завершается, Служба кэшируется: она не активна, но может быть быстро запущена, когда наступает следующий Наступ.

Ответ 4

  • Получить контекст в конструкторе следующим образом:

    public GetDataTask(Context context) {}

  • Создайте интерфейс с помощью метода:

    void onDataRetrieved(String data);

  • Внедрить интерфейс в классе, из которого вы создаете объект Task (например, MainActivity)

  • Передача контекста в интерфейс и вызов метода onDataRetrieved

Ответ 5

Это сработало для меня.

Класс1:

new CallAPI(this).execute("Passing String",data);

Класс1:

private void setData(String data){
    mTextView.setText(data);
}

Затем в реализации AsyncTask onPostExecute:

 @Override
protected void onPostExecute(String result) {
    MainActivity main=new MainActivity();
    main.setData(result);
}

Это вернет то, что вы хотите установитьData, в котором вы когда-либо делаете

Ответ 6

В следующем коде я получаю String (имя директора) из AsyncTask.

public class GetDirector {
    String id;
    private String baseURL = "http://www.omdbapi.com/?i=";
    private String finalURL = "";
    String theDirector;

    public GetDirector(String imdbID) throws ExecutionException, InterruptedException {
        id= imdbID;
        finalURL = baseURL + id + "&plot=full&r=json";
        System.out.println("GetDirector. finalURL= " + finalURL);
        theDirector = new GetDirectorInfo().execute().get();
    }

    public String getDirector (){
        return theDirector;
    }

    private class GetDirectorInfo extends AsyncTask<Void, Void,String> {
        @Override
        protected String doInBackground(Void... params) {
            String directorName = null;

            ServiceHandler sh = new ServiceHandler();

            // Making a request to url and getting response
            String jsonStr = sh.makeServiceCall(finalURL, ServiceHandler.GET);
            System.out.println("Act_DetailsPage. jsonStr= " + jsonStr);

            if (jsonStr != null) {
                try {
                    JSONObject everything = new JSONObject(jsonStr);

                    directorName = everything.getString(JSON_Tags.TAG_DIRECTOR);
                    System.out.println("directorName= "+ directorName);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println("Inside GetDirector. Couldn't get any data from the url");
            }
            return directorName;
        }
    }
}

Ответ 7

Добавьте параметр контекста в конструктор задачи, который будет ссылаться на объект, в котором вы будете хранить результирующие данные.

class PopulateArray extends AsyncTask<Integer, Integer, ArrayList<String>>
{
    Context _context; // context may be what ever activity or object you want to store result in
    PopulateArray(Context context)
    {
        _context = context;
    }
    @Override
    protected ArrayList<String> doInBackground(Integer... integers)
    {
        ArrayList<String> data = new ArrayList<String>();
        //manipulate
        return data;
    }

    @Override
    protected void onPostExecute(ArrayList<String> strings)
    {
        _context.setData(strings);
    }
}

Ответ 8

Этот ONE LINER работал у меня:

String result = MyasyncTask.execute(type, usrPhoneA, usrPWDA).get();

Ответ 9

Единственный способ отправить данные из AsyncTask в пользовательский интерфейс без боли - Otto или Event. Зарегистрируйте метод, который обрабатывает результат в @Subscribe аннотации в пользовательском интерфейсе и post a message с результатом к нему в методе onPostExecute вашего AsyncTask.