Continuing with asynchronous task, this time in Android.
The problem is the same what we have in javascript or another programming language. We have to wait which a specific task ends or wait some data from a query, etc... If these task block the main thread for more of five seconds the ANR dialog is presented to de user. For that you can use threads and runs the task in background. An Android native application commonly is programming with java and the threads aren't a problem. Here can you read more about processes and threads in Android.
For facilitate the task and make it more easy is designed AsyncTask. Here can you read more about that.
Continuing with the same example used in the javascript promises entry, first we must write a class which extends AsyncTask.
private class GetInfoTask extends AsyncTask<String, Void, String> { }
In an asynchronous task we use types. The first indicates the type of the parameters and it is an Array. The second, the type of the progress and it is used for show the progress dialog and finally the type of the result. In this case, the parameters are an array of string, the progress are Void because we will use an spinner in the progress dialog and returns an string.
Android Studio shows a message asking if you want to implement methods as in this image
And if you select Implement methods the result would be like this
doInBackground is one of the four methods that we can use and it is required. This method is invoked on the background and it do the task. The rest of methods are onPreExecute() it is invoked on the UI thread and it is used for setup the task and show the progress dialog. onProgressUpdate(Progress ...) it is invoked on the UI thread and is used to display the progress. onPostExecute(Result) invoked on the UI thread when doInBackground finishes. The Result parameter is the value returned by doInBackground.
In principle it is not necessary use a constructor but if you want to show a progress dialog an application context is needed and the constructor it's a good way to pass it.
So, for our example would be
private ProgressDialog progressDialog; private Context context; public GetInfoTask (Context context) { this.context = context; }
We first declare a ProgressDialog and a Context as global variables on the class and init the Context in the class constructor.
@Override protected void onPreExecute () { progressDialog = new ProgressDialog(context); progressDialog.setCancelable(true); progressDialog.setMessage("Loading data..."); progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); progressDialog.show(); }
In the onPreExecute we initialize the progress dialog with with the Context and show it.
@Override protected String doInBackground(String... urls) { String line = ""; HttpURLConnection httpURLConnection = null; try { URL url = new URL(urls[0]); httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setRequestMethod("GET"); httpURLConnection.setReadTimeout(5000); httpURLConnection.setConnectTimeout(10000); httpURLConnection.setDoOutput(true); httpURLConnection.connect(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream()));
StringBuilder stringBuilder = new StringBuilder(); while ((line = bufferedReader.readLine()) != null) { stringBuilder.append(line + "\n"); } bufferedReader.close(); return stringBuilder.toString(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null;}
doInBackground execs the task, in this case makes a GET connection to a URL passed in the parameter urls[0] and returns a string with the result.
@Override protected void onPostExecute (String result) { progressDialog.dismiss(); String data = ""; if (result != null) try { JSONArray jsonArray = new JSONArray(result); data = jsonArray.getString(2); data = data.substring(2, data.length() - 2); } catch (JSONException e) { e.printStackTrace(); } textView.setText(data); }
Finally in onPostExecute the result is processed, first dismiss the progress dialog and if result is not null parse the JSON Array, extract the data and show on a TextView.
In this example would be missing the progress update, which is where I would enter onProgressUpdate like
@Override protected void onProgressUpdate (Integer... values) { super.onProgressUpdate(values); }
For obtain the values to update on the progress dialog use publishProgress(Progress ...) into doInBackgound.
And finally use it
And finally use it
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final EditText editText = (EditText) findViewById(R.id.editText); Button button = (Button) findViewById(R.id.button); textView = (TextView) findViewById(R.id.textView); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { GetInfoTask getInfoTask = new GetInfoTask(MainActivity.this); Locale locale; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { locale = getResources().getConfiguration() .getLocales().get(0); } else { locale = getResources().getConfiguration().locale; } String finalUrl = "https://" + locale.getLanguage() + wikiURL + "?action=opensearch&search=" + editText.getText().toString() + "&limit=10&explaintext&format=json"; getInfoTask.execute(finalUrl); } });
First we create an object GetInfoTask and finally use it with the string containing the url getInfoTask.execute(finalUrl)
And the result can be like this
Cap comentari:
Publica un comentari a l'entrada