Przykład AsyncTask Android
Czytałem o AsyncTask
i wypróbowałem prosty program poniżej. Ale to chyba nie działa. Jak mogę to zrobić?
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) {
}
}
}
Próbuję zmienić etykietę po 5 sekundach w tle.
To mój Główny.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 answers
Ok próbujesz uzyskać dostęp do GUI przez inny wątek. Zasadniczo nie jest to dobra praktyka.
AsyncTask wykonuje wszystko w doInBackground()
wewnątrz innego wątku, który nie ma dostępu do GUI, w którym znajdują się Twoje widoki.
preExecute()
i postExecute()
oferują dostęp do GUI przed i po ciężkich podnoszenia występuje w tym nowym wątku, można nawet przekazać wynik długiej operacji do postExecute()
, aby następnie pokazać wszelkie wyniki przetwarzania.
Zobacz te linie, gdzie jesteś późniejsza aktualizacja widoku tekstowego:
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
Włóż je do PostExecute()
Tekst TextView zostanie zaktualizowany po zakończeniu doInBackground
.
EDIT: zauważyłem, że Twój słuchacz onClick nie sprawdza, który Widok został wybrany. Najłatwiej jest to zrobić za pomocą instrukcji switch. Mam pełną klasę edytowane poniżej ze wszystkimi sugestiami, aby zaoszczędzić zamieszania.
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) {}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-07 09:21:35
Moja pełna odpowiedź jest tutaj , ale tutaj jest obrazek wyjaśniający, aby uzupełnić inne odpowiedzi na tej stronie. Dla mnie zrozumienie, dokąd zmierzają wszystkie zmienne, było najbardziej mylące na początku.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:34
Jestem pewien, że działa poprawnie, ale próbujesz zmienić elementy interfejsu w wątku tła, a to nie wystarczy.
Zrewiduj swoje połączenie i AsyncTask w następujący sposób:
Wywołanie Klasy
Uwaga: osobiście sugeruję użycie onPostExecute()
wszędzie tam, gdzie wykonujesz swój wątek AsyncTask, a nie w klasie, która rozszerza samą AsyncTask. Myślę, że to sprawia, że kod jest łatwiejszy do odczytania, zwłaszcza jeśli potrzebujesz AsyncTask w wielu miejscach obsługi wyników trochę inaczej.
new LongThread()
{
@Override public void onPostExecute(String result)
{
TextView txt = (TextView) findViewById(R.id.output);
txt.setText(result);
}
}.execute("");
Klasa LongThread (rozszerza 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";
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-30 04:40:07
Stworzyłem prosty przykład użycia AsyncTask Androida. Zaczyna się od onPreExecute(), doInBackground(), publishProgress()
i na końcu onProgressUpdate()
.
W tym doInBackground () działa jako wątek tła, podczas gdy inne działają w wątku interfejsu użytkownika. Nie można uzyskać dostępu do elementu UI w doinbackground (). Sekwencja jest taka sama, jak wspomniałem.
Jeśli jednak chcesz zaktualizować dowolny widget z doInBackground
, możesz publishProgress
z doInBackground
, który wywoła onProgressUpdate
, aby zaktualizować interfejs użytkownika widget.
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);
}
}
Nazwij to tak w swojej aktywności:
new TestAsync().execute();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-25 09:37:23
Przesuń te dwie linie:
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
Z metody AsyncTask doInBackground
i umieścić je w metodzie onPostExecute
. Twój AsyncTask
powinien wyglądać mniej więcej tak:
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);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-12 17:16:50
Najkrótszy przykład robienia czegoś asynchronicznie:
class MyAsyncTask extends android.os.AsyncTask {
@Override
protected Object doInBackground(Object[] objects) {
//do something asynchronously
return null;
}
}
Aby go uruchomić:
(new MyAsyncTask()).execute();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-12 11:17:03
Gdy wykonywane jest zadanie asynchroniczne, zadanie przechodzi przez 4 etapy:
- onPreExecute ()
- doInBackground(Params...)
- onProgressUpdate (Progress...)
- onPostExecute (Result)
Poniżej znajduje się przykład demo
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");
}
}
I po utworzeniu, zadanie jest wykonywane bardzo prosto:
new DownloadFilesTask().execute(url1, url2, url3);
Mam nadzieję, że to ci pomoże...Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-23 11:20:21
Tło / Teoria
AsyncTask pozwala na uruchomienie zadania w wątku tła, podczas publikowania wyników w wątku interfejsu użytkownika.
Użytkownik powinien zawsze mieć możliwość interakcji z aplikacją, więc jest to ważne]} aby uniknąć blokowania głównego (UI) wątku z zadaniami takimi jak pobieranie treści z sieci.Dlatego używamy
AsyncTask
.Oferuje prosty interfejs przez owijanie kolejki wiadomości wątku interfejsu użytkownika i obsługi, która pozwala na wysyłanie i przetwarzanie uruchomionych obiektów i wiadomości z innych wątków.
Realizacja
AsyncTask jest klasą generyczną. (Przyjmuje typy parametryzowane w swoim konstruktorze.)
Używa tych trzech rodzajów generycznych:
Params
- Typ parametrów wysyłanych do zadania po wykonaniu.
Progress
- Typ jednostek postępu opublikowanych podczas obliczeń tła.
Result
- Typ wyniku obliczeń tła.
Nie wszystkie typy są zawsze używane przez zadanie asynchroniczne. Aby oznaczyć Typ jako nieużywany, po prostu użyj typu Void:
private class MyTask extends AsyncTask<Void, Void, Void> { ... }
Te trzy parametry odpowiadają trzem podstawowym funkcjom można nadpisać w AsyncTask
:
doInBackground(Params...)
onProgressUpdate(Progress...)
onPostExecute(Result)
Aby wykonać AsyncTask
Call execute()
z parametrami do wysłania do zadania w tle.
Co Się Dzieje
Na wątku main / UI,
onPreExecute()
nazywa się. (Aby zainicjować coś w tym wątku, na przykład pokazać pasek postępu w interfejsie użytkownika.)-
Na wątku tła,
doInBackground(Params...)
na dzwoniłem. (Parametry są przekazywane do funkcji Execute.)-
Gdzie powinno nastąpić zadanie długotrwałe
Aby użyć AsyncTask, musi nadpisać co najmniej
doInBackground()
.-
Call
publishProgress(Progress...)
aby zaktualizować wyświetlanie postępu w interfejsie użytkownika podczas wykonywania obliczeń w tle. (np. Animuj pasek postępu lub pokaż dzienniki w polu tekstowym.)- to powoduje
onProgressUpdate()
być dzwoniłem.
- to powoduje
-
W wątku tła zwracany jest wynik
doInBackground()
. To uruchamia następny krok.Na wątku main / UI,
onPostExecute()
wywołane z zwróconym wynikiem.
Przykłady
Na przykład blokowanie zadania polega na pobraniu czegoś z sieci.]}- Przykład A pobiera obraz i wyświetla go w widoku ImageView,
- while przykład B pobiera niektóre pliki .
Przykład A
Metoda doInBackground()
pobiera obraz i przechowuje go w obiekcie typu BitMap. Metoda onPostExecute()
pobiera bitmapę i umieszcza ją w widoku 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);
}
}
Przykład 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");
}
}
Przykład B wykonanie
new DownloadFilesTask().execute(url1, url2, url3);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-10 18:34:55
Gdy jesteś w wątku roboczym, nie możesz bezpośrednio manipulować elementami interfejsu użytkownika na Androidzie.
Podczas korzystania z AsyncTask proszę zrozumieć metody wywołania zwrotnego.
Na przykład:
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: Aby uzyskać dostęp do wątku interfejsu użytkownika z wątku roboczego, należy użyć metody runOnUiThread () lub metody post w widoku.
Na przykład:
runOnUiThread(new Runnable() {
textView.setText("something.");
});
or
yourview.post(new Runnable() {
yourview.setText("something");
});
To pomoże Ci lepiej poznać rzeczy. Dlatego w Twoim przypadku musisz ustawić textview w onPostExecute() metoda.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 19:53:25
Polecam ułatwić sobie życie, używając tej biblioteki do prac w tle https://github.com/Arasthel/AsyncJobLibrary
To takie proste..AsyncJob.doInBackground(new AsyncJob.OnBackgroundJob() {
@Override
public void doOnBackground() {
startRecording();
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-29 23:39:17
Przykładowe zadanie asynchroniczne z żądaniem 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);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 19:49:01
Musisz zadeklarować przycisk onclicklistener, po kliknięciu wywoła AsyncTask class DownloadJson, proces zostanie pokazany poniżej:
@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);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-25 04:35:45
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();
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-26 04:12:11
Po Prostu:
LongOperation MyTask = new LongOperation();
MyTask.execute();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 19:47:06
Zmień kod jak podano poniżej:
@Override
protected void onPostExecute(String result) {
runOnUiThread(new Runnable() {
public void run() {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
}
});
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 19:54:57