问题
I have a problem. Here's my code:
public String getXmlFromUrl(String url) {
String xml = null;
new Thread(new Runnable() {
@Override
public void run() {
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
xml = EntityUtils.toString(httpEntity);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).run();
// return XML
return xml;
}
So, how can I use url in my Thread and how can I return xml?
Thank you for your help
回答1:
Android provides an AsyncTask, which perfectly fits your goal.
Example:
private class XMLTask extends AsyncTask<String, String, String> {
@Override
protected void onPreExecute() {
// Do stuff
// For example showing a Dialog to give some feedback to the user.
}
@Override
protected String doInBackground(.. parameters..) {
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
xml = EntityUtils.toString(httpEntity);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return xml;
}
@Override
protected void onPostExecute(String xml) {
// If you have created a Dialog, here is the place to dismiss it.
// The `xml` that you returned will be passed to this method
xml.Dowhateveryouwant
}
}
}
回答2:
Make url final to use it.
If you don't mind blocking until the other thread is completed, make xml into an AtomicReference, and after calling Thread.start() (note you should 'not' call Thread.run() - that will not spawn another thread), use some synchronization tool (such as a CountdownLatch) to wait until the thread finishes before returning xml.
But if you don't mind blocking, why not just execute the code without a separate thread? If you can't block, then you can't return the xml value - you must change the design, perhaps executing an AsyncTask and providing the result asynchronously.
回答3:
You can mark your URL as final and use it within your Runnable like so:
public String getXmlFromUrl(final String url) {
// ...
}
You probably want to define a stateless callback method or class that you can invoke to handle your XML response. You would call it like so:
xml = EntityUtils.toString(httpEntity);
handleXmlResponse(xml);
You could define the method handleXmlResponse as a private method of the class that contains the getXmlFromUrl method if you like.
One thing you might want to consider is using the Executors class to get a newSingleThreadExecutor and pass your Runnable to that instead of creating a new Thread every time you want to fetch some XML:
https://developer.android.com/reference/java/util/concurrent/Executors.html#newSingleThreadExecutor%28%29
Here's an example:
ExecutorService mThreadPool = Executors.newSingleThreadExecutor();
public String getXmlFromUrl(String url) {
String xml = null;
// Note the change here. Everything else remains the same.
mThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
xml = EntityUtils.toString(httpEntity);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
// return XML
return xml;
}
回答4:
2 things:
- This method is a synchronous call so better to use an AsyncTask.
- Use Thread.start() to launch a thread.
来源:https://stackoverflow.com/questions/11657071/android-global-variable-in-thread