Indonesian (Bahasa Indonesia) translation by Ari Gustiawan (you can also view the original English article)
Dalam tutorial ini kita akan menjelajahi Service
komponen dan superclass nya, IntentService
. Anda akan belajar Kapan dan bagaimana menggunakan ini untuk membuat konkurensi solusi untuk long-running background operasi. Kami juga akan mengambil cepat melihat IPC (Inter Process Communication), untuk belajar bagaimana berkomunikasi dengan service yang berjalan pada proses yang berbeda.
Untuk mengikuti tutorial ini Anda akan memerlukan beberapa pemahaman konkurensi di Android. Jika Anda tidak tahu banyak tentang hal ini, Anda mungkin ingin membaca beberapa artikel kami yang lain tentang topik pertama.
- Android SDKAndroid dari awal: Operasi backgroundPaul Trebilcox-Ruiz
- AndroidMemahami nilai-nilai AsyncTask dalam 60 detikPaul Trebilcox-Ruiz
- Android SDKMemahami Konkurensi di Android menggunakan HaMeRTin Megali
- Android SDKPraktis Konkurensi Android dengan HaMeRTin Megali
1. Service komponen
Komponen Service
adalah bagian yang sangat penting dari Android konkurensi framework. Memenuhi kebutuhan untuk melakukan operasi long-running dalam aplikasi, atau persediaan beberapa fungsi untuk aplikasi lain. Dalam tutorial ini kita akan berkonsentrasi pada Service
long-running task kapabilitas, dan bagaimana menggunakan kekuatan ini untuk meningkatkan konkurensi.
Apakah yang dimaksud dengan Service?
Service
ini merupakan komponen sederhana yang dibuat oleh sistem untuk melakukan beberapa pekerjaan long-running yang tidak selalu bergantung pada interaksi pengguna. Ini bisa menjadi independen dari siklus activity dan juga dapat menjalankan pada proses yang berbeda.
Sebelum menyelam ke dalam sebuah diskusi tentang apa yang mewakili sebuah Service
, penting untuk menekankan bahwa meskipun service yang umum digunakan untuk menjalankan long-running background operasi dan untuk melaksanakan tugas-tugas pada proses yang berbeda, sebuah service
tidak mewakili sebuah Thread
atau proses. Itu hanya akan menjalankan dalam thread background atau pada proses berbeda jika itu telah secara eksplisit diminta untuk melakukannya.
Service
yang memiliki dua fitur utama:
- Fasilitas untuk aplikasi untuk memberitahukan sistem tentang sesuatu yang ia ingin lakukan di background.
- Fasilitas untuk suatu aplikasi untuk memaparkan beberapa fungsinya untuk aplikasi lain.
Service dan Thread
Ada banyak kebingungan tentang service dan thread. Ketika Service
dinyatakan, tidak berisi Thread
. Sebagai soal fakta, secara default yang membentang langsung pada thread dan pekerjaan itu berpotensi dapat membekukan aplikasi. (Kecuali jika itu adalah IntentService
, sebuah subclass Service
yang sudah datang dengan sebuah thread worker yang dikonfigurasi.)
Jadi, bagaimana melakukan service menawarkan solusi concurrency? Yah, Service
tidak berisi thread secara default, tetapi dapat dengan mudah dikonfigurasi untuk bekerja dengan thread sendiri atau pool thread. Kita akan melihat lebih banyak tentang hal itu di bawah ini.
Mengabaikan kurangnya built-in thread, Service
adalah solusi yang sangat baik untuk concurrency masalah dalam situasi tertentu. Alasan utama untuk memilih Service atas solusi concurrency lain seperti AsyncTask
atau framework HaMeR adalah:
-
Service
dapat independen activity lifecycle. -
Service
ini cocok untuk menjalankan operasi yang lama. - Service tidak bergantung pada interaksi pengguna.
- Saat menjalankan pada proses yang berbeda, Android dapat mencoba untuk menjaga service hidup bahkan ketika sistem kekurangan sumber daya.
-
Service
yang dapat di-restart untuk melanjutkan pekerjaannya.
Tipe Service
Ada dua jenis Service
, started dan bound.
started service diluncurkan melalui Context.startService().
Umumnya melakukan operasi hanya satu dan itu akan berjalan tanpa batas sampai operasi berakhir, maka itu menutup sendiri. Biasanya, tidak mengembalikan hasil apapun untuk antarmuka pengguna.
bound service diluncurkan melalui Context.bindService(),
dan memungkinkan komunikasi dua arah antara klien dan Service
. Itu juga dapat terhubung dengan beberapa klien. Ia membinasa dirinya ketika tidak ada klien apapun yang terhubung.
Untuk memilih antara dua tipe tersebut, Service
harus menerapkan beberapa callback: onStartCommand()
untuk menjalankan sebagai started service, dan onBind()
untuk menjalankan sebagai bound service. Service
dapat memilih untuk menerapkan hanya salah satu jenis tersebut, tapi dapat juga mengambil keduanya pada waktu yang sama tanpa masalah.
2. Service implementasi
Untuk menggunakan service, extend Service
class dan menimpa metodenya callback, sesuai dengan jenis Service
. Seperti disebutkan sebelumnya, untuk started service metode onStartCommand()
harus diterapkan dan untuk bound servuce, metode onBind()
. Sebenarnya, metode onBind()
harus dinyatakan untuk tipe layanan baik, tetapi dapat mengembalikan null untuk memulai layanan.
public class CustomService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { // Execute your operations // Service wont be terminated automatically return Service.START_NOT_STICKY; } @Nullable @Override public IBinder onBind(Intent intent) { // Creates a connection with a client // using a interface implemented on IBinder return null; } }
-
onStartCommand()
: diluncurkan olehContext.startService().
Hal ini biasanya dipanggil dari suatu activity. Setelah dipanggil, service dapat berjalan tanpa batas dan terserah kepada Anda untuk menghentikannya, memanggilstopSelf()
ataustopService().
-
onBind()
: dipanggil ketika sebuah komponen ingin tersambung ke service. Dipanggil pada sistem olehContext.bindService()
. MengembalikanIBinder
yang menyediakan sebuah antarmuka untuk berkomunikasi dengan klien.
Service siklus hidup ini juga penting untuk mempertimbangkan. Metode onCreate()
dan onDestroy()
harus dilaksanakan untuk menginisialisasi dan menutup setiap sumber daya atau operasi layanan.
Menyatakan Service di Manifest
Komponen Service
harus dinyatakan di manifest dengan <service>
elemen. Dalam pernyataan ini hal ini juga mungkin, tapi tidak wajib, untuk mengatur proses yang berbeda untuk Service
untuk menjalankan.
<manifest ... > ... <application ... > <service android:name=".ExampleService" android:process=":my_process"/> ... </application> </manifest>
2.2. Bekerja dengan Started Service
Untuk memulai started service, Anda harus memanggil metode Context.startService().
Intent
harus dibuat dengan Context
dan Service
class. Setiap informasi yang relevan atau data juga akan dimasukan dalam Intent
ini.
Intent serviceIntent = new Intent(this, CustomService.class); // Pass data to be processed on the Service Bundle data = new Bundle(); data.putInt("OperationType", 99); data.putString("DownloadURL", "https://mydownloadurl.com"); serviceIntent.putExtras(data); // Starting the Service startService(serviceIntent);
Dalam class Service
Anda, metode yang Anda harus khawatir tentang adalah onStartCommand().
Ini adalah metode yang Anda harus memanggil setiap operasi yang Anda ingin menjalankan started service. Anda akan memproses Intent
untuk menangkap informasi yang dikirim oleh klien. startId
mewakili ID unik, otomatis diciptakan untuk permintaan khusus ini dan flags
juga dapat berisi informasi tambahan tentang hal itu.
@Override public int onStartCommand(Intent intent, int flags, int startId) { Bundle data = intent.getExtras(); if (data != null) { int operation = data.getInt(KEY_OPERATION); // Check what operation to perform and send a msg if ( operation == OP_DOWNLOAD){ // make a download } } return START_STICKY; }
OnStartCommand()
mengembalikan int
konstan yang mengontrol perilaku:
-
Service.START_STICKY
: Service ulang jika itu akan dihentikan.
-
Service.START_NOT_STICKY
: Service tidak diaktifkan ulang.
-
Service.START_REDELIVER_INTENT
: Service restart setelah crash dan intent yang kemudian pengolahan akan dikirim ulang.
Seperti disebutkan sebelumnya, started service perlu dihentikan, dinyatakan itu akan berjalan tanpa batas. Ini dapat dilakukan baik oleh Service
dengan memanggil stopSelf()
pada dirinya sendiri atau memanggil stopService()
klien di atasnya.
void someOperation() { // do some long-running operation // and stop the service when it is done stopSelf(); }
Mengikat ke Service
Komponen dapat membuat koneksi dengan service, membangun komunikasi dua arah dengan mereka. Klien harus menghubungi Context.bindService()
, masukan Intent
, antarmuka ServiceConnection
dan flag
sebagai parameter. Service
dapat terikat untuk beberapa klien dan ia akan dibinasakan sekali memiliki klien tidak terhubung.
void bindWithService() { Intent intent = new Intent(this, PlayerService.class); // bind with Service bindService(intent, mConnection, Context.BIND_AUTO_CREATE); }
Dimungkinkan untuk mengirimkan Message
obyek ke service. Untuk melakukannya Anda harus membuat seorang Messenger
pada sisi klien dalam pelaksanaan antarmuka ServiceConnection.onServiceConnected
dan menggunakannya untuk mengirim Message
obyek ke Service.
private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { // use the IBinder received to create a Messenger mServiceMessenger = new Messenger(service); mBound = true; } @Override public void onServiceDisconnected(ComponentName arg0) { mBound = false; mServiceMessenger = null; } };
Hal ini juga mungkin untuk melewati respons Messenger
ke Service
untuk klien untuk menerima pesan. Hati-hati meskipun, karena klien mungkin tidak lagi sekitar untuk menerima service pesan. Anda juga dapat menggunakan BroadcastReceiver
atau broadcast solusi lain.
private Handler mResponseHandler = new Handler() { @Override public void handleMessage(Message msg) { // handle response from Service } }; Message msgReply = Message.obtain(); msgReply.replyTo = new Messenger(mResponseHandler); try { mServiceMessenger.send(msgReply); } catch (RemoteException e) { e.printStackTrace(); }
Hal ini penting untuk unbind dari Service ketika klien sedang dibinasakan.
@Override protected void onDestroy() { super.onDestroy(); // disconnect from service if (mBound) { unbindService(mConnection); mBound = false; } }
Di samping Service
, Anda harus menerapkan metode Service.onBind()
, menyediakan IBinder
yang disediakan dari Messenger
. Ini akan me-relay respons Handler
untuk menangani Message
objek yang diterima dari klien.
IncomingHandler(PlayerService playerService) { mPlayerService = new WeakReference<>(playerService); } @Override public void handleMessage(Message msg) { // handle messages } } public IBinder onBind(Intent intent) { // pass a Binder using the Messenger created return mMessenger.getBinder(); } final Messenger mMessenger = new Messenger(new IncomingHandler(this));
3 Konkurensi menggunakan Service
Akhirnya, itu adalah waktu untuk berbicara tentang bagaimana untuk memecahkan masalah konkurensi dengan menggunakan service. Seperti disebutkan sebelumnya, Service
standar yang tidak berisi thread tambahan apapun dan ia akan berjalan pada Thread
secara default. Untuk mengatasi masalah ini, Anda harus menambahkan worker Thread
, pool thread atau mengeksekusi service
pada proses yang berbeda. Anda juga dapat menggunakan sebuah subclass dari Service
yang disebut IntentService
yang sudah berisi Thread
.
Membuat Service yang berjalan pada Worket Thread
Untuk membuat Service
yang mengeksekusi pada background Thread
Anda bisa membuat Thread
tambahan dan menjalankan pekerjaan yang ada. Namun Android menawarkan solusi yang lebih baik. Salah satu cara untuk mengambil keuntungan terbaik dari sistem adalah untuk mengimplementasikan framework HaMeR dalam service
, misalnya dengan perulangan sebuah Thread
dengan antrian pesan yang dapat memproses pesan tanpa batas.
Hal ini penting untuk memahami bahwa pelaksanaan ini akan memproses tugas secara berurutan. Jika Anda perlu untuk menerima dan memproses beberapa tugas pada waktu yang sama, Anda harus menggunakan pool thread. Menggunakan thread pool berada di luar cakupan tutorial ini dan kami tidak akan berbicara tentang hal itu hari ini.
Untuk menggunakan HaMeR, Anda harus memberikan Service
dengan Looper
, serbuah Handler
, dan HandlerThread
.
private Looper mServiceLooper; private ServiceHandler mServiceHandler; // Handler to receive messages from client private final class ServiceHandler extends Handler { ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); // handle messages // stopping Service using startId stopSelf( msg.arg1 ); } } @Override public void onCreate() { HandlerThread thread = new HandlerThread("ServiceThread", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); }
Jika framework HaMeR asing bagi Anda, baca tutorial kami pada HaMer untuk Android concurrency.
- Android SDKMemahami konkurensi di Android menggunakan HaMeRTin Megali
- Android SDKPraktis Konkurensi Android dengan HaMeRTin Megali
IntentService
Jika ada tidak perlu untuk Service
untuk dipelihara untuk waktu yang lama, Anda dapat menggunakan IntentService
, sebuah subclass Service
yang siap untuk menjalankan tugas-tugas pada background thread. Secara internal, IntentService
adalah Service
dengan implementasi yang sangat mirip dengan yang diusulkan di atas.
Untuk menggunakan class ini, Semua harus Anda lakukan adalah extend onHandleIntent()
, hook metode yang akan dipanggil setiap kali klien memanggil startService()
di Service
ini. Hal ini penting untuk diingat bahwa IntentService
akan berhenti segera setelah pekerjaan selesai.
public class MyIntentService extends IntentService { public MyIntentService() { super("MyIntentService"); } @Override protected void onHandleIntent(Intent intent) { // handle Intents send by startService } }
IPC (Inter Procss Communication)
Service
yang dapat berjalan pada Process
yang sama sekali berbeda, terlepas dari semua tugas-tugas yang terjadi pada proses utama. Proses yang memiliki alokasi memori, thread group, dan pengolahan prioritas. Pendekatan ini dapat sangat berguna ketika Anda perlu untuk bekerja secara independen dari proses utama.
Komunikasi antara proses yang berbeda disebut IPC (Inter Process Communication). Dalam Service
ada dua cara utama untuk melakukan IPC: menggunakan Messenger
atau implementasi sebuah antarmuka AIDL
.
Kami telah belajar cara mengirim dan menerima pesan antara service. Semua yang harus Anda lakukan adalah menggunakan membuat Messenger
menggunakan contoh IBinder
menerima selama proses sambungan dan menggunakannya untuk mengirim balasan Messenger
kembali ke Service
.
private Handler mResponseHandler = new Handler() { @Override public void handleMessage(Message msg) { // handle response from Service } }; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { // use the IBinder received to create a Messenger mServiceMessenger = new Messenger(service); Message msgReply = Message.obtain(); msgReply.replyTo = new Messenger(mResponseHandler); try { mServiceMessenger.send(msgReply); } catch (RemoteException e) { e.printStackTrace(); } }
Antarmuka AIDL
adalah solusi yang sangat kuat yang memungkinkan memanngil langsung langsung pada metode Service
yang berjalan pada proses yang berbeda dan cocok untuk digunakan ketika Service
Anda benar-benar kompleks. Namun, AIDL
rumit untuk melaksanakan dan jarang digunakan, sehingga penggunaannya tidak akan dibahas dalam tutorial ini.
4. kesimpulan
Service dapat sederhana atau kompleks. Tergantung pada kebutuhan aplikasi Anda. Aku mencoba untuk menutupi tanah sebanyak mungkin pada tutorial ini, namun saya telah terfokus hanya pada menggunakan sevice untuk tujuan konkurensi dan ada lebih banyak kemungkinan untuk komponen ini. Saya ingin anda mempelajari lebih lanjut, lihat dokumentasi dan Android panduan.
Sampai jumpa lagi!
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weeklyEnvato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post