Bu derste intent service kavramından bahsediyoruz.
Daha önce started service konusunu incelemiştik. Bu servis geriye herhangi bir değer göndermeyen ve de onu çağıran componentten bağımsız olarak arka planda çalışan bir servis türüydü. yani onu çağıran activity kapansa bile çalışmaya devam ediyordu.
Intent servis de aslında started servicesin özel bir türü diyebiliriz(Service sınıfından extend olur). Started servisten farkı ise yapı olarak uzun süren işlemleri ele alacak şekilde tasarlanmıştır. Yani main thread üzerinde değil de worker threadde çalışacak şekilde oluşturulmuş, uzun sürecek işlemler için gelen bir servis türüdür.
onHandleIntent() methodu içerisine yazacağımız kodlar worker thread’de çalıştırılarak main threadi meşgul etmez, bu sayede kullanıcı uygulamayla etkileşim halinde olabilir. (Started servislerde bu işlem için Asynctask sınıfını kullanmıştık) Eğer servisimiz içerisinde uzun sürecek bir işlem yapacaksak intent servis tercih edilebilir.
Ayrıca yine kendi içinde bir kuyruk yapısı olduğundan birden fazla uzun sürecek işlemi servisimizde gerçekleştirebiliriz. Bu sınıf tüm işlemleri kuyruğa alır ve sırasıyla yapar.
Kuyruktaki tüm uzun/kısa süren işlemler bittiğinde de otomatik olarak servisi durdurur. Herhangi bir stopService veya stopSelf() methodu yazmamıza gerek kalmaz.
Started service gibi intent servicede de varsayılan olarak geriye bilgi gönderilmez. Ama bazen böyle bir ihtiyaç duyulabilir. Bu durumda bazı yapıları kullanarak servisimizden activity’e veri gönderebilir, layoutumuzdaki view öğelerini güncelleyebilir veya en basitinden bir toast mesajı gösterebilirz. Bu dersteki yapacağımız örnekte bir resultreceiver kullanarak servisimizden activity’e veri gönderdik.
Öncelikle ResultReceiver sınıfından extend ettiğimiz bir sınıf oluşturduk. Bu sınıfın nesnesini de servisi başlattığımız intent ile service sınıfımıza gönderdik.(ResultReceiver sınıfı Parcelable interfacesini implemente ettiği için böyle bir işlem yapabiliyoruz.)
Parcelable:Android’de intent veya bundle ile veri gönderirken string, integer, double, boolean vs dışında object göndermek istersek ilgili object nesnelerinin sınıfı parcelable interface’sinden implemente edilmişse putExtra methodu ile göndermemizi sağlayan interfacedir.
Servis sınıfına gönderdiğimiz resultreceiver nesnesine istediğimiz verileri koyup send methodu ile activity’e gönderip servis ile activity arasında veri alışverişini sağlayabiliyoruz.send methoduna int resultCode ile Bundle tipinde resultData parametrelerini koyarak servisten activity’e verimizi gönderiyoruz.
send methoduyla geriye veri gönderince onReceiveResult methodu tetiklenir ve gelen verileri burda ele alabiliriz. Ama bu method yine worker thread üzerinde çalıştığı için biz main threadde bulunan view nesnelerimize ulaşamayız. Burda da handler sınıfını kullanmamız gerekiyor.
Handler : post methoduna bir tane runnable nesnesi sunarak çalıştığı background thread’den main threade ulaşan ve oradaki öğelere müdahele edebilen, güncelleyebilen yapıdır.
Runnable : run methodunu sunan ve bu methodun içerisinde yazılan kodları main thread üzerinde gerçekleştiren interfacedir. Genellikle worker thread üzerinden ui thread yani main thread’e müdahale edemeyeceğimiz için Runnable interfacesindeki run methodunu kullanırız.
Artık servisimizden activity’mize yaptığımız işlem ile ilgili veri alabilir ve bu veri sayesinde main thread içindeki viewları istediğimiz gibi güncelleyebiliriz.
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 |
public class MainActivity extends AppCompatActivity { Handler handler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void startIntentService(View view) { ResultReceiver myResultReceiver = new MyResultReceiver(null); Intent intent = new Intent(MainActivity.this, MyIntentService.class); intent.putExtra("receiver", myResultReceiver); intent.putExtra("sleepTime", 5); startService(intent); } public class MyResultReceiver extends ResultReceiver { private final String TAG = MyResultReceiver.class.getSimpleName(); public MyResultReceiver(Handler handler) { super(handler); } @Override protected void onReceiveResult(int resultCode, final Bundle resultData) { super.onReceiveResult(resultCode, resultData); if (resultCode == 15 && resultData != null) { handler.post(new Runnable() { @Override public void run() { Log.e(TAG, "onReceiveResult methodu çağrıldı thread :" + Thread.currentThread().getName()); Toast.makeText(MainActivity.this, "Gelen mesaj:" + resultData.getInt("donguSirasi"), Toast.LENGTH_SHORT).show(); } }); } } } } |
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 |
public class MyIntentService extends IntentService { private static final String TAG = MyIntentService.class.getSimpleName(); @Override public void onCreate() { Log.i(TAG, "oncreate methodu " + Thread.currentThread().getName() + " threadi üzerinden cagrildi"); super.onCreate(); } public MyIntentService() { super("MyWorkerThread"); } @Override protected void onHandleIntent(@Nullable Intent intent) { Log.i(TAG, "onHandleIntent methodu " + Thread.currentThread().getName() + " threadi üzerinden cagrildi"); int sleepTime = intent.getIntExtra("sleepTime", 1); ResultReceiver resultReceiver = intent.getParcelableExtra("receiver"); int kontrol = 1; while (kontrol <= sleepTime) { try { Thread.sleep(1000); Bundle bundle = new Bundle(); bundle.putInt("donguSirasi", kontrol); resultReceiver.send(15, bundle); } catch (InterruptedException e) { e.printStackTrace(); } kontrol++; } } @Override public void onDestroy() { Log.i(TAG, "onDestroy methodu " + Thread.currentThread().getName() + " threadi üzerinden cagrildi"); super.onDestroy(); } } |