Пример AsyncTask Android
Я читал о 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 секунд в фоновом режиме.
Это мой главная.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>
15 ответов:
Ok вы пытаетесь получить доступ к GUI через другой поток. Это, в основном, не очень хорошая практика.
AsyncTask выполняет все в
doInBackground()внутри другого потока, который не имеет доступа к GUI, где ваши взгляды.
preExecute()иpostExecute()предлагаем вам доступ к GUI до и после того, как тяжелый подъем происходит в этом новом потоке, вы даже можете передать результат длительной операции в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");из вашего AsyncTask
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 шага:
- onPreExecute()
- doInBackground (Params...)
- onProgressUpdate(прогресс...)
- 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);Я надеюсь, что это поможет вам...
Фон / Теория
AsyncTask позволяет запускать задачу в фоновом потоке при публикации результатов в потоке пользовательского интерфейса.
пользователь должен всегда иметь возможность взаимодействовать с приложением, так что это важно чтобы не блокировать основной (UI) поток С такими задачами, как загрузка контента из интернета.
вот почему мы используем
AsyncTask.он предлагает простой интерфейс обертывание очереди сообщений потока пользовательского интерфейса и обработчика, которые позволяют отправлять и обрабатывать запускаемые объекты и сообщения из других потоков.
реализация
AsyncTask является общим классом. (Это занимает параметризованные типы в своем конструкторе.)
он использует эти три основных типа:
Params- тип параметров, передаваемых задаче при выполнении.
Progress- тип единиц прогресса, опубликованных во время фоновых вычислений.
Result- тип результата фоновой задачи.не все типы всегда используются асинхронной задачи. Чтобы пометить тип как неиспользуемый, просто используйте тип Void:
private class MyTask extends AsyncTask<Void, Void, Void> { ... }эти три параметра соответствуют трем основным функциям вы можете переопределить в
AsyncTask:
doInBackground(Params...)onProgressUpdate(Progress...)onPostExecute(Result)для выполнения AsyncTask
вызов
execute()с параметрами для отправки в фоновую задачу.что Бывает
в основном потоке / UI,
onPreExecute()называется. (Чтобы инициализировать что-то в этом потоке, например, показать индикатор выполнения в пользовательском интерфейсе.)на фоне потока,
doInBackground(Params...)называется. (Параметры, переданные в функцию execute.)
где должна произойти длительная задача
должен переопределить at по крайней мере
doInBackground()для использования AsyncTask.вызов
publishProgress(Progress...)чтобы обновить отображение прогресса в пользовательском интерфейсе, пока выполняется фоновое вычисление. (например, анимировать индикатор выполнения или показывать журналы в текстовом поле.)
- это приводит к
onProgressUpdate()называться.в фоновом потоке результат возвращается из
doInBackground(). Этот триггер следующий шаг.в основном потоке / UI,
onPostExecute()вызывается с возвращенным результатом.примеры
снова используя пример задачи блокировки, чтобы загрузить что-то из интернета,
- пример загрузки изображения и отображает его в ImageView,
- пока пример B загружает некоторые файлы.
Пример A
The
doInBackground()метод загружает изображение и сохраняет его в объекте типа BitMap. ЭлементonPostExecute()метод берет растровое изображение и помещает его в ImageView.class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { ImageView bitImage; public DownloadImageTask(ImageView bitImage) { this.bitImage = bitImage; } protected Bitmap doInBackground(String... urls) { String urldisplay = urls[0]; Bitmap mBmp = null; try { InputStream in = new java.net.URL(urldisplay).openStream(); mBmp = BitmapFactory.decodeStream(in); } catch (Exception e) { Log.e("Error", e.getMessage()); e.printStackTrace(); } return mBmp; } protected void onPostExecute(Bitmap result) { bitImage.setImageBitmap(result); } }Пример B
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"); } }пример выполнения B
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; } }к вашему сведению: Чтобы получить доступ к потоку пользовательского интерфейса из рабочего потока, вы либо используете метод runOnUiThread (), либо метод post в своем представлении.
например:
runOnUiThread(new Runnable() { textView.setText("something."); }); or yourview.post(new Runnable() { yourview.setText("something"); });Это поможет вам знать, что лучше. Следовательно, в вашем случае вам нужно установить ваш textview в методе onPostExecute ().
Я бы рекомендовал сделать вашу жизнь проще, используя эту библиотеку для фоновых работ https://github.com/Arasthel/AsyncJobLibrary
это так просто..
AsyncJob.doInBackground(new AsyncJob.OnBackgroundJob() { @Override public void doOnBackground() { startRecording(); } });
пример асинхронной задачи с запросом 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); } }
вам нужно объявить кнопку 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); } }
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(); } }
измените свой код, как указано ниже:
@Override protected void onPostExecute(String result) { runOnUiThread(new Runnable() { public void run() { TextView txt = (TextView) findViewById(R.id.output); txt.setText("Executed"); } }); }

Comments