Пример Android для AsyncTask

Я читал об AsyncTask , и я попробовал простую программу ниже. Но, похоже, это не работает. Как я могу заставить его работать?

 package com.test; import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.provider.Settings.System; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.view.View.OnClickListener; public class AsyncTaskActivity extends Activity { Button btn; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = (Button) findViewById(R.id.button1); btn.setOnClickListener((OnClickListener) this); } public void onClick(View view){ new LongOperation().execute(""); } private class LongOperation extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params) { for(int i=0;i<5;i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } TextView txt = (TextView) findViewById(R.id.output); txt.setText("Executed"); return null; } @Override protected void onPostExecute(String result) { } @Override protected void onPreExecute() { } @Override protected void onProgressUpdate(Void... values) { } } } 

Я просто пытаюсь изменить ярлык через 5 секунд в фоновом режиме.

Это мой main.xml :

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <ProgressBar android:id="@+id/progressBar" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:indeterminate="false" android:max="10" android:padding="10dip"> </ProgressBar> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Start Progress" > </Button> <TextView android:id="@+id/output" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Replace"/> </LinearLayout> 

Хорошо, вы пытаетесь получить доступ к графическому интерфейсу через другой поток. Это, в основном, не является хорошей практикой.

AsyncTask выполняет все в doInBackground() внутри другого потока, который не имеет доступа к графическому интерфейсу, в котором находятся ваши представления.

preExecute() и postExecute() предлагают вам доступ к графическому интерфейсу до и после тяжелого подъема в этом новом потоке, вы можете даже передать результат длительной операции postExecute() чтобы затем показать результаты обработки.

См. Эти строки, в которых вы позже обновляете TextView:

 TextView txt = (TextView) findViewById(R.id.output); txt.setText("Executed"); 

Поместите их в PostExecute()

Затем вы увидите текст TextView, обновленный после завершения doInBackground .

EDIT: Я заметил, что ваш слушатель onClick не проверяет, какой вид был выбран. Я считаю, что самый простой способ сделать это – с помощью операторов switch. У меня есть полный класс, отредактированный ниже со всеми предложениями, чтобы сохранить путаницу.

 import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.provider.Settings.System; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.view.View.OnClickListener; public class AsyncTaskActivity extends Activity implements OnClickListener { Button btn; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = (Button) findViewById(R.id.button1); // because we implement OnClickListener we only have to pass "this" // (much easier) btn.setOnClickListener(this); } public void onClick(View view) { // detect the view that was "clicked" switch (view.getId()) { case R.id.button1: new LongOperation().execute(""); break; } } private class LongOperation extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params) { for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.interrupted(); } } return "Executed"; } @Override protected void onPostExecute(String result) { TextView txt = (TextView) findViewById(R.id.output); txt.setText("Executed"); // txt.setText(result); // might want to change "executed" for the returned string passed // into onPostExecute() but that is upto you } @Override protected void onPreExecute() {} @Override protected void onProgressUpdate(Void... values) {} } } 

Мой полный ответ здесь , но вот пояснительный образ, чтобы дополнить другие ответы на этой странице. Для меня понимание того, где были все переменные, было самой запутанной частью в начале.

Введите описание изображения здесь

Я уверен, что он выполняется правильно, но вы пытаетесь изменить элементы пользовательского интерфейса в фоновом потоке, и это не будет сделано.

Пересмотрите свой вызов и AsyncTask следующим образом:

Класс вызова

Примечание. Я лично предлагаю использовать onPostExecute() везде, где вы выполняете поток AsyncTask, а не в классе, который расширяет сам AsyncTask. Я думаю, что это упрощает чтение кода, особенно если вам нужна AsyncTask в нескольких местах, обрабатывающих результаты, несколько отличающиеся.

 new LongThread() { @Override public void onPostExecute(String result) { TextView txt = (TextView) findViewById(R.id.output); txt.setText(result); } }.execute(""); 

Класс LongThread (расширяет AsyncTask):

 @Override protected String doInBackground(String... params) { for(int i = 0; i < 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } return "Executed"; } 

Концепция и код здесь

Я создал простой пример использования AsyncTask для Android. Он начинается с onPreExecute(), doInBackground(), publishProgress() и, наконец, onProgressUpdate() .

В этом doInBackground () работает как фоновый поток, а другой работает в потоке пользовательского интерфейса. Вы не можете получить доступ к элементу пользовательского интерфейса в doInBackground (). Последовательность такая же, как я уже упоминал.

Однако, если вам нужно обновить какой-либо виджет из doInBackground вы можете publishProgress из doInBackground который будет вызывать onProgressUpdate для обновления виджета пользовательского интерфейса.

 class TestAsync extends AsyncTask<Void, Integer, String> { String TAG = getClass().getSimpleName(); protected void onPreExecute (){ super.onPreExecute(); Log.d(TAG + " PreExceute","On pre Exceute......"); } protected String doInBackground(Void...arg0) { Log.d(TAG + " DoINBackGround","On doInBackground..."); for(int i=0; i<10; i++){ Integer in = new Integer(i); publishProgress(i); } return "You are at PostExecute"; } protected void onProgressUpdate(Integer...a){ super.onProgressUpdate(a); Log.d(TAG + " onProgressUpdate", "You are in progress update ... " + a[0]); } protected void onPostExecute(String result) { super.onPostExecute(result); Log.d(TAG + " onPostExecute", "" + result); } } 

Назовите это так:

 new TestAsync().execute(); 

Справочник разработчика здесь

Переместите эти две строки:

 TextView txt = (TextView) findViewById(R.id.output); txt.setText("Executed"); 

Из вашего doInBackground метода doInBackground и поместите их в метод onPostExecute . Ваша AsyncTask должна выглядеть примерно так:

 private class LongOperation extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params) { try { Thread.sleep(5000); // no need for a loop } catch (InterruptedException e) { Log.e("LongOperation", "Interrupted", e); return "Interrupted"; } return "Executed"; } @Override protected void onPostExecute(String result) { TextView txt = (TextView) findViewById(R.id.output); txt.setText(result); } } 

Самый короткий пример для асинхронного выполнения:

 class MyAsyncTask extends android.os.AsyncTask { @Override protected Object doInBackground(Object[] objects) { //do something asynchronously return null; } } 

Чтобы запустить его:

 (new MyAsyncTask()).execute(); 

Когда выполняется асинхронная задача, задача выполняет 4 этапа:

  1. onPreExecute ()
  2. doInBackground (Params …)
  3. onProgressUpdate (Прогресс …)
  4. onPostExecute (Результат)

Ниже приведен пример демонстрации

 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); // Escape early if cancel() is called if (isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } } 

И как только вы создали, задача выполняется очень просто:

  new DownloadFilesTask().execute(url1, url2, url3); 

Я надеюсь, что это поможет вам…

Когда вы находитесь в рабочем потоке, вы не можете напрямую манипулировать элементами пользовательского интерфейса на Android.

Когда вы используете AsyncTask, пожалуйста, поймите методы обратного вызова.

Например:

 public class MyAyncTask extends AsyncTask<Void, Void, Void>{ @Override protected void onPreExecute() { // Here you can show progress bar or something on the similar lines. // Since you are in a UI thread here. super.onPreExecute(); } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); // After completing execution of given task, control will return here. // Hence if you want to populate UI elements with fetched data, do it here. } @Override protected void onProgressUpdate(Void... values) { super.onProgressUpdate(values); // You can track you progress update here } @Override protected Void doInBackground(Void... params) { // Here you are in the worker thread and you are not allowed to access UI thread from here. // Here you can perform network operations or any heavy operations you want. return null; } } 

FYI: для доступа к потоку пользовательского интерфейса из рабочего потока вы либо используете метод runOnUiThread (), либо метод post на вашем представлении.

Например:

 runOnUiThread(new Runnable() { textView.setText("something."); }); or yourview.post(new Runnable() { yourview.setText("something"); }); - runOnUiThread(new Runnable() { textView.setText("something."); }); or yourview.post(new Runnable() { yourview.setText("something"); }); - runOnUiThread(new Runnable() { textView.setText("something."); }); or yourview.post(new Runnable() { yourview.setText("something"); }); 

Это поможет вам лучше узнать все. Следовательно, в вашем случае вам нужно установить текстовое представление в методе onPostExecute ().

Я бы рекомендовал сделать вашу жизнь проще, используя эту библиотеку для фоновых работ https://github.com/Arasthel/AsyncJobLibrary

Это просто ..

 AsyncJob.doInBackground(new AsyncJob.OnBackgroundJob() { @Override public void doOnBackground() { startRecording(); } }); 

Пример задачи Async с запросом POST:

 List<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("key1", "value1")); params.add(new BasicNameValuePair("key1", "value2")); new WEBSERVICEREQUESTOR(URL, params).execute(); class WEBSERVICEREQUESTOR extends AsyncTask<String, Integer, String> { String URL; List<NameValuePair> parameters; private ProgressDialog pDialog; public WEBSERVICEREQUESTOR(String url, List<NameValuePair> params) { this.URL = url; this.parameters = params; } @Override protected void onPreExecute() { pDialog = new ProgressDialog(LoginActivity.this); pDialog.setMessage("Processing Request..."); pDialog.setIndeterminate(false); pDialog.setCancelable(false); pDialog.show(); super.onPreExecute(); } @Override protected String doInBackground(String... params) { try { DefaultHttpClient httpClient = new DefaultHttpClient(); HttpEntity httpEntity = null; HttpResponse httpResponse = null; HttpPost httpPost = new HttpPost(URL); if (parameters != null) { httpPost.setEntity(new UrlEncodedFormEntity(parameters)); } httpResponse = httpClient.execute(httpPost); httpEntity = httpResponse.getEntity(); return EntityUtils.toString(httpEntity); } catch (Exception e) { } return ""; } @Override protected void onPostExecute(String result) { pDialog.dismiss(); try { } catch (Exception e) { } super.onPostExecute(result); } } 
  private class AsyncTaskDemo extends AsyncTask<Void, Void, Void> { @Override protected void onPreExecute() { super.onPreExecute(); // Showing progress dialog progressDialog = new ProgressDialog(this); progressDialog.setMessage("Loading..."); progressDialog.setCancelable(false); progressDialog.show(); } @Override protected Void doInBackground(Void... arg0) { //do code here return null; } @Override protected void onPostExecute(Void result) { super.onPostExecute(result); // Dismiss the progress dialog if (progressDialog.isShowing()) { progressDialog.dismiss(); } } @Override protected void onCancelled() { super.onCancelled(); progressDialog.dismiss(); Toast toast = Toast.makeText(getActivity(), "Error is occured due to some probelm", Toast.LENGTH_LONG); toast.setGravity(Gravity.TOP, 25, 400); toast.show(); } } 

Просто:

 LongOperation MyTask = new LongOperation(); MyTask.execute(); 

Вам нужно объявить кнопку onclicklistener, как только щелкнуть по ней вызовом класса AsyncTask DownloadJson, процесс будет показан ниже:

 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = (Button) findViewById(R.id.button1); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new DownloadJson().execute(); } }); } 

  // DownloadJSON AsyncTask private class DownloadJson extends AsyncTask<Void, Void, Void> { @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected Void doInBackground(Void... params) { newlist = new ArrayList<HashMap<String, String>>(); json = jsonParser.makeHttpRequest(json, "POST"); try { newarray = new JSONArray(json); for (int i = 0; i < countdisplay; i++) { HashMap<String, String> eachnew = new HashMap<String, String>(); newobject = newarray.getJSONObject(i); eachnew.put("id", newobject.getString("ID")); eachnew.put("name", newobject.getString("Name")); newlist.add(eachnew); } } } catch (JSONException e) { Log.e("Error", e.getMessage()); e.printStackTrace(); } return null; } @Override protected void onPostExecute(Void args) { newlisttemp.addAll(newlist); NewAdapterpager newadapterpager = new NewAdapterpager(ProcesssActivitypager.this,newlisttemp); newpager.setAdapter(newadapterpager); } } 

Измените свой код следующим образом:

 @Override protected void onPostExecute(String result) { runOnUiThread(new Runnable() { public void run() { TextView txt = (TextView) findViewById(R.id.output); txt.setText("Executed"); } }); }