Как получить строку из 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
Ответы
Ответ 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
.