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
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
}
}
}
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.
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;
}