While programming on the android, it is important to remember that lengthy operations that may take more than 20ms are to be avoided on the main UI thread. A UI thread is the main thread in which all of your activities run. Operations that take more than 20ms cause your application’s UI to appear sluggish and unresponsive. Sometimes, you android system may mark you application as unresponsive and display the infamous “Application is not responding” dialog. This cannot be good for your application.
The trick here is to perform all such operations in a background thread. Fortunately, android api’s provide a very useful class that you can subclass according to your needs for performing such operations without creating runnable and thread classes. This is the AsyncTask class. Please refer to the android SDK reference for documentation of the AsyncTask class.
Below I reproduce a helper subclass I wrote specifically for invoking web services in a background thread.
public class AsyncInvokeURLTask extends AsyncTask<Void, Void, String> { private final String mNoteItWebUrl = "your-url.com"; private ArrayList<NameValuePair> mParams; private OnPostExecuteListener mPostExecuteListener = null; public static interface OnPostExecuteListener{ void onPostExecute(String result); } AsyncInvokeURLTask( ArrayList<NameValuePair> nameValuePairs, OnPostExecuteListener postExecuteListener) throws Exception { mParams = nameValuePairs; mPostExecuteListener = postExecuteListener; if (mPostExecuteListener == null) throw new Exception("Param cannot be null."); } @Override protected String doInBackground(Void... params) { String result = ""; // Create a new HttpClient and Post Header HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost(mNoteItWebUrl); try { // Add parameters httppost.setEntity(new UrlEncodedFormEntity(mParams)); // Execute HTTP Post Request HttpResponse response = httpclient.execute(httppost); HttpEntity entity = response.getEntity(); if (entity != null){ InputStream inStream = entity.getContent(); result = convertStreamToString(inStream); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return result; } @Override protected void onPostExecute(String result) { if (mPostExecuteListener != null){ try { JSONObject json = new JSONObject(result); mPostExecuteListener.onPostExecute(json); } catch (JSONException e){ e.printStackTrace(); } } } private static String convertStreamToString(InputStream is){ BufferedReader reader = new BufferedReader( new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } } // AsyncInvokeURLTask
The argument ArrayList<NameValuePair> to the class’s constructor is used to pass name value pairs to the invoked service. You can use this class as follows:
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); nameValuePairs.add(new BasicNameValuePair("command", "do_get_shop_list")); nameValuePairs.add(new BasicNameValuePair("arg1", String.valueOf(getUserID()))); AsyncInvokeURLTask task = new AsyncInvokeURLTask( nameValuePairs, new AsyncInvokeURLTask.OnPostExecuteListener { public void onPostExecute(String result) { // Do here whatever you want to do when the task completes. // The data returned by the invoked service will be contained // in the result argument } }; task.execute();
hey hi,
will this code work if my mNoteItWebUrl starts with ftp://mydomain.
I don’t think so. This code uses HttpClient, HttpPost and HttpResponse objects which are specifically meant for the http POST method. I’m sorry I’m not aware of how to use ftp.
There are 2 bugs in this example, the first one is in the json on part number 1 line 56.
error: method onPostExecute in interface OnPostExecuteListener cannot be applied to given types;
mPostExecuteListener.onPostExecute(json);
required: String
found: JSONObject
reason: actual argument JSONObject cannot be converted to String by method invocation conversion
The other one is in the part number 2 on line 07 where it complains about a missing ( or {.
I cant seem to fix neither of them. Help would be usefull.
Tried this, but when I put the last block of code to make a call, I get a compile error:
“The constructor AsyncInvokeURLTask(ArrayList, new onPostExecute(){}) is undefined”
Any help?
Fixed. You need @Override above the onPostExecute method
Hi. This code is very helpful; though as stated in an answer on Stackoverflow.com (http://stackoverflow.com/a/3291713/1635441), the postExecute method is being called on the UI thread, so if the task is a long one, it will possible cause the applcation to crash.