Android 如何从 AsyncTask 取回字符串?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10972114/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get a string back from AsyncTask?
提问by Paul
I have the following class:
我有以下课程:
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);
}
}
And I am trying to call it like this:
我试图这样称呼它:
String output = null;
output = new getURLData().execute("http://www.domain.com/call.php?locationSearched=" + locationSearched);
But the output variable isn't getting data, instead I am getting an error:
但是输出变量没有获取数据,而是出现错误:
Type mismatch: cannot convert from AsyncTask<String,Integer,String> to String
回答by K-ballo
The method execute
returns the AynscTask
itself, you need to call get
:
该方法execute
返回AynscTask
本身,您需要调用get
:
output =
new getURLData()
.execute("http://www.example.com/call.php?locationSearched=" + locationSearched)
.get();
This will start a new thread (via execute
) while blocking the current thread (via get
) until the work from the new thread has been finished and the result has been returned.
这将启动一个新线程(via execute
),同时阻塞当前线程(via get
),直到新线程的工作完成并返回结果。
If you do this, you just turned your asynctask into a syncone.
如果你这样做,你只是把你的异步任务变成了同步任务。
However, the problem with using get
is that because it blocks, it needs to be called on a worker thread. However, AsyncTask.execute()
needs to be called on the main thread. So although this code could work, you may get some undesired results. I also suspect that get()
is under-tested by Google, and it is possible that they introduced a bug somewhere along the line.
但是,使用的问题get
在于,因为它阻塞,所以需要在工作线程上调用它。但是,AsyncTask.execute()
需要在主线程上调用。因此,尽管此代码可以工作,但您可能会得到一些不希望的结果。我还怀疑get()
Google 未对此进行测试,并且他们可能在此过程中的某个地方引入了一个错误。
Reference: AsyncTask.get
回答by pawelzieba
I'd rather create callback than block UI thread. In your class create method which will be invoked when data arrive. For example:
我宁愿创建回调而不是阻止 UI 线程。在您的类中 create 方法将在数据到达时调用。例如:
private void setData(String data){
mTextView.setText(data);
}
Then in AsyncTask implement onPostExecute:
然后在 AsyncTask 中实现 onPostExecute:
@Override
protected void onPostExecute(String result) {
setData(result);
}
And then somewhere in code just execute task:
然后在代码中的某处执行任务:
new getURLData().execute(...
When task finishes setData is invoked and mTextView is filled.
当任务完成时调用 setData 并填充 mTextView。
AsyncTask.get() will blok your UI, so there is no reason to use AsyncTask.
AsyncTask.get() 会阻塞你的 UI,所以没有理由使用 AsyncTask。
回答by Joe Malin
If the user clicks the button, then has to wait for the content, what do they do meanwhile?
如果用户点击按钮,那么必须等待内容,他们同时做什么?
Why not do this:
为什么不这样做:
- User clicks button.
- You check for connectivity. If the user isn't connected to the Internet, tell them.
- You start an IntentService by sending an Intent to send the HTTP request.
- When the request finishes, you post a notification.
- The user clicks the notification, which returns to an Activity that can do the next step.
- 用户点击按钮。
- 您检查连通性。如果用户未连接到 Internet,请告诉他们。
- 你通过发送一个 Intent 来启动一个 IntentService 来发送 HTTP 请求。
- 请求完成后,您会发布通知。
- 用户点击通知,返回到一个可以进行下一步的活动。
This allows the user to go off and do whatever while the request is being processed.
这允许用户在处理请求时离开并做任何事情。
An IntentService runs in the background on its own thread. When it receives an Intent, it runs onHandleIntent(). When that method finishes, the Service is cached: it's not active, but it can re-start quickly when the next Intent arrives.
IntentService 在后台运行在它自己的线程上。当它接收到一个 Intent 时,它运行 onHandleIntent()。当该方法完成时,服务被缓存:它不是活动的,但是当下一个 Intent 到达时它可以快速重新启动。
回答by Matthias Herrmann
Get the context in the constructor like this:
public GetDataTask(Context context) {}
Create an Interface with the method:
void onDataRetrieved(String data);
Implement the Interface in the class from where you are creating the Task object (e.g.
MainActivity
)Cast the Context to the Interface and call the onDataRetrieved Method
像这样在构造函数中获取上下文:
public GetDataTask(Context context) {}
使用该方法创建一个接口:
void onDataRetrieved(String data);
在创建 Task 对象的类中实现接口(例如
MainActivity
)将上下文转换为接口并调用 onDataRetrieved 方法
回答by francisqueins
This ONE LINER worked for me:
这个 ONE LINER 对我有用:
String result = MyasyncTask.execute(type, usrPhoneA, usrPWDA).get();
回答by isabsent
The only way to send data from AsyncTask
to UI without pain is Ottoor Eventbus. Register a method which will handle a result under @Subscribe
annotation in UI and post
a message
with a result to it in onPostExecute
method of your AsyncTask
.
将数据从AsyncTask
UI 轻松发送到 UI的唯一方法是Otto或事件总线。注册将处理结果下的方法@Subscribe
在UI注释和post
一个message
带有结果它在onPostExecute
你的方法AsyncTask
。
回答by Gene
In the following code, I get a String (directorName) back from AsyncTask.
在下面的代码中,我从 AsyncTask 得到一个 String (directorName)。
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;
}
}
}
回答by Dragas
Add a context parameter to task's constructor which would refer to object where you'd store resulting data.
向任务的构造函数添加一个上下文参数,该参数将引用您将存储结果数据的对象。
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);
}
}