Viac na
Príklad AsyncTask pre Android
Čítal som o AsyncTask
a vyskúšal som jednoduchý program uvedený nižšie. Ale zdá sa, že nefunguje. Ako to môžem spraviť, aby to fungovalo?
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) {
}
}
}
Snažím sa len zmeniť štítok po 5 sekundách v procese na pozadí.
Toto je môj súbor 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>
665
3
Dobre, snažíte sa získať prístup ku grafickému rozhraniu prostredníctvom iného vlákna. To v zásade nie je dobrý postup.
AsyncTask vykonáva všetko v
doInBackground()
vnútri iného vlákna, ktoré nemá prístup ku grafickému rozhraniu, kde sú vaše pohľady.Funkcie
preExecute()
apostExecute()
vám ponúkajú prístup ku grafickému používateľskému rozhraniu pred a po vykonaní ťažkej operácie v tomto novom vlákne, dokonca môžete výsledok dlhej operácie odovzdať funkciipostExecute()
, aby sa potom zobrazili všetky výsledky spracovania.Pozrite si tieto riadky, kde neskôr aktualizujete svoj TextView:
vložte ich do
onPostExecute()
Potom uvidíte text vášho TextView aktualizovaný po dokončení
doInBackground
.EDIT: Všimol som si, že váš poslucháč onClick nekontroluje, ktorý View bol vybraný. Zistil som, že najjednoduchší spôsob, ako to urobiť, je pomocou príkazov switch. Nižšie mám upravenú kompletnú triedu so všetkými návrhmi, aby som ušetril zmätok.
Som si istý, že sa vykonáva správne, ale vy sa snažíte zmeniť prvky používateľského rozhrania vo vlákne na pozadí a to nejde.
Upravte svoje volanie a AsyncTask takto:
Trieda volania
Poznámka: Osobne odporúčam používať
onPostExecute()
všade tam, kde vykonávate vlákno AsyncTask, a nie v triede, ktorá rozširuje samotnú AsyncTask. Myslím, že to uľahčuje čítanie kódu, najmä ak potrebujete AsyncTask na viacerých miestach, ktoré spracúvajú výsledky mierne odlišne.Trieda LongThread (rozširuje AsyncTask):
Presuňte tieto dva riadky:
z metódy
doInBackground
vašej AsyncTask'a vložte ich do metódyonPostExecute
. VašaAsyncTask
by mala vyzerať takto: