Bu dersimizde sürekli olarak adı geçen threadlerden detaylı bir şekilde bahsediyoruz.
Android uygulaması açıldığında cihazda onunla ilgili bir process başlatılır. Bu process üzerinde 4 ana komponentin işlemlerini yapacak main thread (ui thread veya ana thread) de oluşturulur. Ve bir activity’deki butona tıklanma işlemi, bir broadcast receiverın tetiklendiği bir event, startservice methoduyla işlenecek servis kodları veya content provider ile bir sorgunun çalıştırılması işlemleri bu thread üzerinde gerçekleştirilir.
Yani 4 ana komponentin tüm işlemleri default olarak main thread üzerinde çalıştırılır. Bu threadi bir mesaj kuyruğu olarak düşünebilirsiniz. Bu kuyruğa eklenen her olay sırasıyla çağrılıp çalıştırılır(looper yapısı). Siz eğer bu kuyruğa uzun sürecek bir işlemi koyarsanız, kuyruktaki işlemler o işlem bitmeden çalıştırılamayacağı için uygulama crash olabilir. Bu yüzden sürekli olarak 5 saniyeden uzun sürecek işlemleri main thread üzerinde değil de farklı bir thread (worker thread) üzerinde gerçekleştirmemiz gerektiğini söylüyoruz.
Uygulamayı kapanmaya zorlamamak ya da main threadi kitlememek için dosyalarla çalışma gibi, resim işleme gibi, networksel işlemler gibi uzun sürecek işlemleri farklı bir thread üzerinde yapmalıyız. Daha önce böyle bir durum için AsyncTask sınıfından bahsetmiştik. Bu derste bu sınıfın temeli olan Thread sınıfını kullanarak işin detayını anlamaya çalışalım.
Bunun için thread sınıfını oluştururken bir runnable interface nesnesi gerekiyor. Bu interface’deki run() methodunun içine yazacağımız işlemler main thread üzerinde değil farklı bir thread üzerinde çalıştırılır. Uzun sürecek ve main threadi kitleyecek işlemleri bu run methodunun içine yazmalıyız.
Bunun dışında runOnUiThread methodu da kullanılabilir. Bu method da sizden runnable nesnesi bekler ve bunu oluşturduğunuzda beliren run methodu içine uzun sürecek işlemle ilgili kodları yazabilirsiniz. Bu methodu main thread üzerinde çalıştırdıysanız işleminiz hemen gerçekleştirilecektir. Ama bu methodu worker thread üzerinde çağırırsanız işleminiz main thread’deki event queue (event yada mesaj kuyruğuna) post edilecek yani gönderilecektir. Sırası geldiğinde de gerçekleştirilecektir.
Şunu unutmamak gerekir. Worker thread içinden main thread’e direk olarak erişemezsiniz ve de view öğelerini güncelleyemezsiniz.
Mesela activity’de tanımlı bir textviewınız var ve bunun içeriğini worker thread içindeyken güncellemek istiyorsunuz. Yani worker thread üzerinden main thread içindeki event queue’ye bir event göndermek istiyorsunuz. Bu mümkün değildir ve farklı yapılar kullanmanız gerekir. Mesela yukarıda anlatılan runOnUiThread methodu gibi..
Ayrıca worker thread içindeyken güncellemek istediğiniz viewı kullarak da main thread’e ulaşabilirsiniz. post() ve postDelayed() methodları bu işe yarar. textview.post() dediğinizde post methodu içine runnable nesnesi göndererek işleminizi main thread’e ulaştırıp worker thread’den main threade erişmeniz mümkündür.
Özetle bir worker thread direk olarak main thread’e ve onun mesaj kuyruğuna erişemez. Bunun için bir handler ve de bir runnable nesnesi gerekir. Yukarıdaki yöntemlerle siz bu runnable nesnesini kuyruğa sokarak işleminizi yaptırabilirsiniz.
Bu derste yazılan kodlar aşağıdaki gibidir:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
public class MainActivity extends AppCompatActivity { private final static String TAG = MainActivity.class.getSimpleName(); boolean donguCalisiyor; int donguSayisi; TextView textView; //Thread thread; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.tvSayi); /*MyThread myThread=new MyThread(); thread=new Thread(myThread);*/ } public void startThread(View view) { // thread.start(); new Thread(new Runnable() { @Override public void run() { donguCalisiyor = true; while (donguCalisiyor) { try { Thread.sleep(1000); Log.i(TAG, "Döngü sayısı :" + donguSayisi + " Thread adı :" + Thread.currentThread().getName()); /* runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(getApplicationContext(), ""+donguSayisi, Toast.LENGTH_SHORT).show(); } });*/ /*textView.post(new Runnable() { @Override public void run() { textView.setText(""+donguSayisi); } });*/ textView.postDelayed(new Runnable() { @Override public void run() { textView.setText("" + donguSayisi); } }, 5000); donguSayisi++; } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } public void stopThread(View view) { donguCalisiyor = false; } /* public class MyThread implements Runnable{ @Override public void run() { donguCalisiyor=true; while(donguCalisiyor){ try { Thread.sleep(1000); Log.i(TAG, "Döngü sayısı :"+ donguSayisi + " Thread adı :"+ Thread.currentThread().getName()); donguSayisi ++; } catch (InterruptedException e) { e.printStackTrace(); } } } } */ } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.emrealtunbilek.threadanlatim.MainActivity"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="14dp" android:onClick="startThread" android:text="Start Thread" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/button" android:layout_centerHorizontal="true" android:layout_marginTop="24dp" android:onClick="stopThread" android:text="Stop Thread" /> <TextView android:id="@+id/tvSayi" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/button2" android:layout_centerHorizontal="true" android:layout_marginTop="34dp" android:text="TextView" /> </RelativeLayout> |