AsyncTask` hakkında bir şeyler okuyordum ve aşağıdaki basit programı denedim. Ancak çalışmıyor gibi görünüyor. Nasıl çalışmasını sağlayabilirim?
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) {
}
}
}
Sadece arka plan işleminde 5 saniye sonra etiketi değiştirmeye çalışıyorum.
Bu benim main.xml dosyam:
<?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>
Tamam, GUI'ye başka bir iş parçacığı üzerinden erişmeye çalışıyorsunuz. Bu, esas olarak, iyi bir uygulama değildir.
AsyncTask, doInBackground()
içindeki her şeyi, görünümlerinizin bulunduğu GUI'ye erişimi olmayan başka bir iş parçacığının içinde yürütür.
preExecute()ve
postExecute()bu yeni iş parçacığında ağır işler yapılmadan önce ve yapıldıktan sonra GUI'ye erişmenizi sağlar, hatta uzun işlemin sonucunu
postExecute()` işlevine aktararak işlem sonuçlarını gösterebilirsiniz.
TextView'inizi daha sonra güncelleyeceğiniz bu satırlara bakın:
TextView txt = findViewById(R.id.output);
txt.setText("Executed");
bunları onPostExecute()
içine koyun
Daha sonra doInBackground
tamamlandıktan sonra TextView metninizin güncellendiğini göreceksiniz.
EDIT: onClick dinleyicinizin hangi Görünümün seçildiğini kontrol etmediğini fark ettim. Bunu yapmanın en kolay yolunun switch deyimleri olduğunu düşünüyorum. Karışıklığı önlemek için tüm önerilerle birlikte aşağıda düzenlenmiş eksiksiz bir sınıfım var.
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;
AsyncTask<?, ?, ?> runningTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = findViewById(R.id.button1);
// because we implement OnClickListener we only have to pass "this"
// (much easier)
btn.setOnClickListener(this);
}
@Override
public void onClick(View view) {
// detect the view that was "clicked"
switch (view.getId()) {
case R.id.button1:
if (runningTask != null) runningTask.cancel(true);
runningTask = new LongOperation();
runningTask.execute();
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// cancel running task(s) to avoid memory leaks
if (runningTask != null) runningTask.cancel(true);
}
private final class LongOperation extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... params) {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// we were cancelled, stop sleeping!
}
}
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
}
}
}
Düzgün çalıştığından eminim, ancak arka plan iş parçacığında kullanıcı arayüzü öğelerini değiştirmeye çalışıyorsunuz ve bu işe yaramayacak.
Çağrınızı ve AsyncTask'ı aşağıdaki gibi revize edin:
Çağrı Sınıfı
Not: Ben şahsen onPostExecute()
fonksiyonunu AsyncTask iş parçacığını çalıştırdığınız her yerde kullanmanızı öneririm, AsyncTask'ın kendisini genişleten sınıfta değil. Özellikle AsyncTask'a birden fazla yerde ihtiyacınız varsa ve sonuçları biraz farklı işliyorsanız, kodun okunmasını kolaylaştırdığını düşünüyorum.
new LongThread() {
@Override public void onPostExecute(String result) {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText(result);
}
}.execute("");
LongThread sınıfı (AsyncTask'ı genişletir):
@Override
protected String doInBackground(String... params) {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "Executed";
}
Bu iki çizgiyi taşıyın:
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
AsyncTask'ınızın doInBackground
yönteminden çıkarın ve onPostExecute
yöntemine koyun. AsyncTask`ınız aşağıdaki gibi görünmelidir:
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);
}
}