Android Programlama – Progress Bar, Thread
Merhaba arkadaşlar, bu yazımızda daha önceki yazımızda geliştirdiğimiz form uygulamasını biraz daha geliştireceğiz. Bu uygulamamızda progress bar üzerinde duracağız. Bir önceki yazımızı okumayanlar buradan okuyabilir. Okumak istemeyenler bir önceki uygulamayı indirip üzerinde devam edebilirler.
Diğer yazılarımız;
- Eclipse Üzerine Android Sdk Kurulumu (Resimli ve Detaylı Windows – Linux – Mac İçin Anlatım)
- Android Programlama – Basit Form Uygulaması
- Android Programlama – TableLayout-Radio Button
- Android Programlama – ListView-Spinner-AutoCompleteTextView-Adapter
- Android Programlama – Özelleştirilmiş ListView
- Android Programlama – TabView, TabHost, TabWidget, FrameLayout – DatePicker
- Android Programlama – Menu, Toast, AlertDialog
Bu yazımızın amacı, programımız arka planda bir işle uğraşırken (örneğin veri indirme veya database işlemi) kullanıcıya görsel olarak işin ilerlediğini göstermek. Böylece kullanıcı ne olduğunun farkında olup, işin bitmesini bekleyecek. Ancak biz bu örneğimizde gerçekten uzun bir işlem yapamayacağımız için, arka planda çalışacak olan iş yapmacık olacak.
Kullanıcıya progress bar iki şekilde gösterilebilir. Ya widget olarak ya da Activity nin bir özelliği olarak. Biz activity nin özelliğini kullanacağız. Bu progress bar ekranın ortasında olmayacakta, ekranın başlık kısmında yer alacak.
İlk iş olarak bu özelliği aktif etmemiz gerekiyor. Bunun için onCreate() metodu içinde setContentView() dan önce ve super classı çağırdıktan sonra şu kodları yazmalıyız.
super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_PROGRESS); setContentView(R.layout.main); |
İkinci adım ise bizim arka planda çalışacak işi simule edecek ortamı hazırlamak. Bunun için Activity içine someWork() isminde metot tanımlıyoruz. İçinde de sleep() metodunu çağırıyoruz. Böylece burada bir iş yapılıyormuş havası veriyoruz.
private void someWork(final int incr) { SystemClock.sleep(incr); // gerçek uygulamada burada asıl iş yapılacak. } |
250 ms çalışan bu metodu şimdi biraz çağırma vakti. Runnable cinsinden tanımladığımız task ımız (yani threadimiz) 30 kere someWork metodunu çağırarak toplamda 6 saniyelik bir iş olacak.
private Runnable task=new Runnable() { public void run() { for (int i=0;i<30;i++) { someWork(250); } } }; |
Şimdi bu işi nerede çağıracağız? En basit yöntem bir buton koymak, ben bir menü seçeneği daha oluşturuyorum. Bu seçenek seçildiğinde işimiz çalışmaya başlayacak. Bunun için option.xml dosyama yeni item ekliyorum.
<item android:id="@+id/run" android:title="Çalıştır" android:icon="@drawable/run" /> |
Şimdi seçenek seçildiğinde yakalamamız lazım. Bunun için ise onOptionsItemSelected() metodunda düzenlemeye gidiyoruz.
/** * Çalıştır seçeneği seçildi ise */ else if (item.getItemId()==R.id.run) { new Thread(task).start(); } |
Şimdi artık yaşanan olayları progress bar da görme zamanı. İşimiz başladığında progress bar çalışmaya başlayacak, güncellenecek ve iş bittiğinde kaybolacak.
Activity altında int progress tanılıyoruz. Daha sonra onOptionsItemSelected() altında progress barı görünür yapıyoruz.
/** * Çalıştır seçeneği seçildi ise */ else if (item.getItemId()==R.id.run) { setProgressBarVisibility(true); progress=0; new Thread(task).start(); } |
Ve someWork() metodu içinde güncelleme işlemi yapıyoruz.
private void someWork(final int incr) { /** * Progress barı update ediyoruz */ runOnUiThread(new Runnable() { public void run() { progress+=incr; setProgress(progress); } }); SystemClock.sleep(incr); // gerçek uygulamada burada asıl iş yapılacak. } |
son olarak ta işimiz bittiğinde progress bar ı gizlememiz gerekiyor.
/** * Yeni task oluşturarak yeni bir thread olarak çalıştırıyoruz */ private Runnable task=new Runnable() { public void run() { for (int i=0;i<30;i++) { someWork(250); } /** * İşlem bittiğinde progress barı gizliyoruz. */ runOnUiThread(new Runnable() { public void run() { setProgressBarVisibility(false); } }); } }; |
Çalıştırdığımızda elde ettiğimiz görüntü
Activity classımızın son hali ise;
package kodmerkezi.net.basitForm; import java.util.ArrayList; import java.util.List; import kodmerkezi.net.basitForm.R.menu; import android.app.Activity; import android.app.AlertDialog; import android.app.TabActivity; import android.content.DialogInterface; import android.os.Bundle; import android.os.SystemClock; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.DatePicker; import android.widget.EditText; import android.widget.ImageView; import android.widget.ListView; import android.widget.RadioGroup; import android.widget.Spinner; import android.widget.TabHost; import android.widget.TextView; import android.widget.Toast; public class BasitFormActivity extends TabActivity { /** * Kitapları Liste halinde tutacağımız için ArrayList cinsinde tanımlıyoruz */ List<Book> books = new ArrayList<Book>(); /** * ListView ile bağlantıyı kuracak adaptörümüz */ ArrayAdapter<Book> adapter=null; /** * listeden seçtiğimiz elemanın detayları için bu değişkenleri localden buraya taşıdık. */ EditText name=null; EditText author=null; RadioGroup types=null; DatePicker date=null; EditText comment=null; Menu menu=null; /** * Yeni kaydolan veya henüz listeden seçimi yapılmış kitabımızı tutacak değişken */ Book current = null; /** * Progress bar için değişken */ private int progress; /** * AutoComplete özelliği için yazarlarımız */ private static final String[] AUTHORS = new String[] { "Gurcan Kavakçı", "Mehmet S.", "Ali T.", "Hasan G.", "Saffet C." }; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_PROGRESS); setContentView(R.layout.main); /** * degişkenleri view elemanlarına bağlıyoruz */ name=(EditText)findViewById(R.id.name); author=(EditText)findViewById(R.id.author); types=(RadioGroup)findViewById(R.id.types); date=(DatePicker)findViewById(R.id.date); comment=(EditText)findViewById(R.id.comment); Button save = (Button)findViewById(R.id.save); save.setOnClickListener(onSave); ListView list=(ListView)findViewById(R.id.books); /** * adaptörümüzü yaratıyoruz. */ adapter = new BookAdapter(); /** * ListView ile adaptör bağlantısını sağlıyoruz */ list.setAdapter(adapter); /** * Yazar için AutoComplete özelliği */ ArrayAdapter<String> adapter_author = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, AUTHORS); AutoCompleteTextView textView = (AutoCompleteTextView)findViewById(R.id.author); textView.setAdapter(adapter_author); /** * 1. tab için */ TabHost.TabSpec spec=getTabHost().newTabSpec("tag1"); spec.setContent(R.id.books); spec.setIndicator("List", getResources().getDrawable(R.drawable.books)); getTabHost().addTab(spec); /** * 2. tab için */ spec=getTabHost().newTabSpec("tag2"); spec.setContent(R.id.details); spec.setIndicator("Details", getResources() .getDrawable(R.drawable.detail)); getTabHost().addTab(spec); getTabHost().setCurrentTab(0); /** * listemizin listener ile bağlantısını kuruyoruz */ list.setOnItemClickListener(onListClick); } /** * Aslinda işimizi görecek metod bu ancak şimdilik suni bir iş yapıyor. */ private void someWork(final int incr) { /** * Progress barı update ediyoruz */ runOnUiThread(new Runnable() { public void run() { progress+=incr; setProgress(progress); } }); SystemClock.sleep(incr); // gerçek uygulamada burada asıl iş yapılacak. } /** * Yeni task oluşturarak yeni bir thread olarak çalıştırıyoruz */ private Runnable task=new Runnable() { public void run() { for (int i=0;i<30;i++) { someWork(250); } /** * İşlem bittiğinde progress barı gizliyoruz. */ runOnUiThread(new Runnable() { public void run() { setProgressBarVisibility(false); } }); } }; /** * Menümüzü yaratıyoruz */ @Override public boolean onCreateOptionsMenu(Menu menu) { this.menu=menu; new MenuInflater(this).inflate(R.menu.option, menu); return(super.onCreateOptionsMenu(menu)); } /** * Menüden seçim yapıldığında kullanıyoruz */ @Override public boolean onOptionsItemSelected(MenuItem item) { /** * Eğer yorum seçeneği seçilmişse */ if (item.getItemId()==R.id.commentToast) { String message="Kitap Seçilmedi"; if (current!=null) { message=current.getComment(); } /** * ekranda bilgi mesajı gösteren yapı. * İlk eleman bulunduğu activity * ikinci eleman gösterilecek mesaj * üçüncü eleman ise gösterilecek süre (short yada long) */ //Toast.makeText(this, message, Toast.LENGTH_LONG).show(); /** * Toast Mesajı yerine kullanacağız. */ AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this); //başlığı alertDialogBuilder.setTitle("Kitaba Yapılan Yorum"); //mesajı alertDialogBuilder.setMessage(message); //ekranın cancel edilememesi alertDialogBuilder.setCancelable(false); //kullanıcıya sunulan seçenek alertDialogBuilder.setNeutralButton("Tamam",new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog,int id) { // if this button is clicked, just close // the dialog box and do nothing dialog.cancel(); } }); //set ettiğimiz bu bilgilerden bir dialog yaratıp gösteriyoruz AlertDialog alertDialog = alertDialogBuilder.create(); //gosteriyoruz alertDialog.show(); return(true); } /** * Detay sayfası seçilmiş ise */ else if (item.getItemId()==R.id.otherOption){ if(getTabHost().getCurrentTab()==0) { MenuItem m = menu.findItem(R.id.otherOption); m.setTitle("Liste"); m.setIcon(R.drawable.books); getTabHost().setCurrentTab(1); } else { MenuItem m = menu.findItem(R.id.otherOption); m.setTitle("Detay"); m.setIcon(R.drawable.detail); getTabHost().setCurrentTab(0); } } /** * Çalıştır seçeneği seçildi ise */ else if (item.getItemId()==R.id.run) { setProgressBarVisibility(true); progress=0; new Thread(task).start(); } return(super.onOptionsItemSelected(item)); } /** * Formumuzda yeni kitap kaydında çalışıyor */ private View.OnClickListener onSave = new View.OnClickListener() { public void onClick(View v) { /** * local olması için buraya taşıdık. */ current = new Book(); EditText name = (EditText)findViewById(R.id.name); EditText author = (EditText)findViewById(R.id.author); DatePicker date = (DatePicker)findViewById(R.id.date); EditText comment = (EditText)findViewById(R.id.comment); current.setName(name.getText().toString()); current.setAuthor(author.getText().toString()); current.setDay(date.getDayOfMonth()); current.setMonth(date.getMonth()); current.setYear(date.getYear()); current.setComment(comment.getText().toString()); RadioGroup types=(RadioGroup)findViewById(R.id.types);//radio buttonlardan seçeneği alıyoruz /** * aldığımız seçenği switch ile ilgili şekilde kaydediyoruz. */ switch (types.getCheckedRadioButtonId()) { case R.id.adventure: current.setType("adventure"); break; case R.id.biography: current.setType("biography"); break; case R.id.documentary: current.setType("documentary"); break; } /** * adaptöre yeni elemanı ekliyoruz. */ adapter.add(current); } }; /** * Listeden bir eleman seçilirse çalışıyor */ private AdapterView.OnItemClickListener onListClick=new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> parent,View view, int position,long id) { /** * listeden bir eleman seçildiğinde, global değişkenlerimizi seçilen liste * elemanına göre dolduruyruz */ current=books.get(position); name.setText(current.getName()); author.setText(current.getAuthor()); date.init(current.getYear(),current.getMonth(), current.getDay(), null); comment.setText(current.getComment()); if (current.getType().equals("adventure")) { types.check(R.id.adventure); } else if (current.getType().equals("biography")) { types.check(R.id.biography); } else { types.check(R.id.documentary); } getTabHost().setCurrentTab(1); } }; /** * Kitaplarımızı liste halinde listViewda görünmesini sağlayan adapter */ public class BookAdapter extends ArrayAdapter<Book> { public BookAdapter() { super(BasitFormActivity.this,android.R.layout.simple_list_item_1,books); } public View getView(int position, View convertView, ViewGroup parent) { View row=convertView; BookHolder holder = null; if (row==null) { LayoutInflater inflater=getLayoutInflater(); row=inflater.inflate(R.layout.satir,parent,false); holder=new BookHolder(row); row.setTag(holder); } else { holder=(BookHolder)row.getTag(); } holder.populateFrom(books.get(position)); return row; } } /** * Kitaplarımızı tutan yapı */ static class BookHolder { private TextView name=null; private TextView author=null; private ImageView icon=null; private View row=null; BookHolder(View row) { this.row=row; name=(TextView)row.findViewById(R.id.name); author=(TextView)row.findViewById(R.id.author); icon=(ImageView)row.findViewById(R.id.icon); } void populateFrom(Book b) { name.setText(b.getName()); author.setText(b.getAuthor()); if (b.getType().equals("adventure")) { icon.setImageResource(R.drawable.blue); } else if (b.getType().equals("biography")) { icon.setImageResource(R.drawable.red); } else { icon.setImageResource(R.drawable.yellow); } } } } |
Bugünkü çalışmamızda, programın arka planda çalıştırması gereken uzun soluklu bir iş olduğunda, bu işin ilerlemesini kullanıcıya göstererek, kullanıcıyı bilgilendirmek amaçlanmıştır. Burada yapılan çalışma ikinci bir thread yapısıdır. Bu yüzden arkada iş ilerlerken siz başka bir iş yapabilirsiniz.
Projenin kaynak kodlarını buradan indirebilirsiniz. Rar şifresi: www.kodmerkezi.netBunlara da Göz Atmak İsteyebilirsiniz.
<<< Önceki: Android Programlama – Menu, Toast, AlertDialog
Sonraki: Hosting Çözümleri >>>
Yorum Bırakın!