همانطور که می دانید سرویس ابزاری است که توسط آن دستورات را به بکگراند برده و درآنجا اجرا می کنیم. در یک برنامه می توان از تعداد زیادی سرویس بطور همزمان استفاده کرد و برای متوقف کردن آنها هم می توان از داخل برنامه و یا بصورت داخلی با دستور stopSelf عمل کرد.
تفاوت های اصلی IntentService با Service در این است که بعد از ایجاد آن در Worker دیگری جدا از thread برنامه قرار می گیرد. برنامه به راحتی می تواند با آن ارتباط برقرار کند و خود IntentService نیز بعد از انجام وظایف محول شده بسته می شود و لازم نیست نگران هندل کردن آن باشیم. همانگونه مطلع هستید توسط Service می توانیم چندین task موازی داشته باشیم در صورتی که اگر چند نمونه از intentService تولید کنیم همگی در یک thread بصورت صف پشت هم قرار می گیرند تا پس از اتمام دیگری اجرا شوند و به نظر می رسد برای انجام یکسری دستورات batch بصورت متوالی و پشت سرهم هستند، بسیار مناسب باشد.
in short, a Service is a broader implementation for the developer to set up background operations, while an IntentService is useful for “fire and forget” operations, taking care of background Thread creation and cleanup
جدول زیر نمایانگر تفاوت های عمده می باشد:
به مثال زیر توجه کنید: می خواهیم بعد از گرفتن ورودی توسط کاربر IntentService ای اجرا کنیم که کلاسی به نام MyData ساخته و بعد از مقداردهی آن به برنامه بازگرداند و برنامه نیز در صورت باز بودن آن داده را نمایش دهد. برای ارتباط بین سرویس و برنامه از
BroadcastReceiver
استفاده می کنم و برای پاس دادن داده از اینترفیس
Serializable
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 |
public class MyIntentService extends IntentService { public MyIntentService(){ super("my intent service"); } @Override protected void onHandleIntent(Intent intent) { String myName = intent.getStringExtra("NAME"); SystemClock.sleep(1000); MyData myData = new MyData(); myData.setId(110); myData.setName(myName); myData.setLasname("tajik"); myData.setDate(DateFormat.format("dd/MM/yy h:mm:ss aa", System.currentTimeMillis()).toString()); Intent broadCastIntent = new Intent(); broadCastIntent.setAction("mahdi.broadcast.action"); Bundle myboundle = new Bundle(); myboundle.putSerializable("mahdi.data",myData); broadCastIntent.putExtra("mahdi.bundle",myboundle); LocalBroadcastManager myBroadCastManager = LocalBroadcastManager.getInstance(this); myBroadCastManager.sendBroadcast(broadCastIntent); Log.i("TAG", "onHandleIntent: name"+myName); } } |
کلاس MyData به صورت زیر می باشد:
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 |
public class MyData implements Serializable { int Id; String name; String lasname; String date; public String getDate() { return date; } public void setDate(String date) { this.date = date; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getLasname() { return lasname; } public void setLasname(String lasname) { this.lasname = lasname; } public int getId() { return Id; } public void setId(int id) { Id = id; } } |
حال سرویس را در Manifest تعریف می کنیم:
1 |
<service android:name=".MyIntentService"></service> |
برای ارتباط برقرار کردن از سرویس کافی است که Broadcast Receiver ای تعریف کنیم با فیلتری مشترک که در MainActivity باشد. همانطور که می دانید یکی از بهترین روش های ارتباط سرویس و برنامه استفاده از Broad Cast Receiver است. روش بدین صورت است که برنامه گوش خود را به فیلتر خاصی تیز می کند! (register) سپس سرویس نیز پیغامی با فیلتر موردنظر منتشر می کند. پس برنامه به صدای سرویس عکس العمل نشان داده و اطلاعات را گرفته و سپس نمایش می دهد. به همین سادگی.
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 |
public class MainActivity extends AppCompatActivity { BroadcastReceiver myReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Bundle myBoundle = intent.getBundleExtra("mahdi.bundle"); MyData mData = (MyData) myBoundle.getSerializable("mahdi.data"); Toast.makeText(MainActivity.this, "Received mData.name=" + mData.getName(), Toast.LENGTH_SHORT).show(); } }; } @Override protected void onStart() { super.onStart(); LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver, new IntentFilter("mahdi.broadcast.action")); } @Override protected void onStop() { super.onStop(); LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver); } public void startService(View v) { EditText edit = (EditText) findViewById(R.id.editText); String name = edit.getText().toString().trim(); Intent i = new Intent(MainActivity.this, MyIntentService.class); i.putExtra("NAME", name); startService(i); } } |
بعد از لمس شدن دکمه شروع در صورتی که برنامه را نبسته باشید پیغام Toast را مشاهده خواهید کرد.
آزمایش کردن اجرای چند IntentService باهم نیز بسیار ساده است. کافی است سرویس خودمان را چندبار پشت سر هم اییجاد کنید و خواهید دید که هرکدام بعد از ۵ ثانیه ( یعنی تمام شدن کارهای سرویس قبلی) اجرا خواهند شد. یعنی بصورت موازی نبوده و در صف قرار می گیرند.
در جواب یکی از دوستان سوالی پرسیده بودند که آیا این هم مانند سرویس در صورت بسته شدن برنامه اجرا می شود یا خیر، باید عرض کنم “بله”. IntentService هم مانند سرویس در صورت بسته بودن برنامه اجرا می شود. برای تست این قضیه می توانید
MainActivity
را به این صورت تغییر داده و نتیجه را ببینید:
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 MainActivity extends AppCompatActivity { BroadcastReceiver myReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Bundle myBoundle = intent.getBundleExtra("mahdi.bundle"); MyData mData = (MyData) myBoundle.getSerializable("mahdi.data"); Toast.makeText(MainActivity.this, "Received mData.name=" + mData.getName(), Toast.LENGTH_SHORT).show(); } }; for(int i=0; i<10 ; i++){ startService("name"+i); } this.finish(); } @Override protected void onStart() { super.onStart(); LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver, new IntentFilter("mahdi.broadcast.action")); } @Override protected void onStop() { super.onStop(); LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver); } public void startService(String name) { EditText edit = (EditText) findViewById(R.id.editText); // String name = edit.getText().toString().trim(); Intent i = new Intent(MainActivity.this, MyIntentService.class); i.putExtra("NAME", name); startService(i); } |
تلاش من در آموزش ها این است که نه تنها مورد آموزش بلکه موارد دیگری را که به نظرم مفید است استفاده کنم. به عنوان مثال در این بحث از
BroadcastReceiver
و
Serializable
استفاده کردم. مطمئناً خیلی از دوستان آشنایی کامل دارند و استفاده می کنند. اما دوستانی که برایشان تازه است حتماً راجع به آنها خوانده و در صورت نیاز سوال بپرسند. امیدوارم مطالب مفید بوده باشد. درصورتی که سوال و یا نکته نظری داشتید کامنت بگذارید. خیلی ممنون.
منبع: بایت کد
سلام
من کد شمارو کپی کردم اما تست نداده.
ضمنا میخواستم ببینم میشه از این سرویس برای زمانی ک برنامه بسته هم استفاده کرد؟
سلام. تغییرات کوچکی در کد اعمال کردم. حتماً متدstartService را استفاده کنید. چون در مثال من در فایل xml استفاده شده که شاید شما آن را فراموش کرده اید که این خط را اضافه کنید: android:onClick=”startService”
در جواب سوالتان هم باید بگویم بله. مانند سرویس بعد از خروج برنامه هم کار می کند و بسیار مناسب دستوراتی هست که توالی دارند و باید پشت هم اجرا شوند. اگر بازهم سوالی داشتید در خدمت هستم.