分类:C#、Android、VS2015;
创建日期:2016-03-01
为了进一步简化Intent过滤器的用法,Android系统又提供了一个IntentService类,这样一来,你也不需要重写其他的方法了,直接实现一个继承自IntentService的类,然后重写OnHandleIntent方法即可。
IntentService类继承自Service类。这个类自动使用工作线程处理所有Service的启动请求(即:对IntentService的每次请求都会自动启动一个线程去处理它)。
因为大多数started服务都不需要“并发”处理多个请求(这实际上是一个危险的多线程情况),所以最佳方式也许就是用IntentService类来实现你的服务。
总之,只要Started Service不需要“并发”处理多个请求,首选的办法就是用IntentService来实现。
1、IntentService的工作机制
IntentService将自动执行以下步骤:
创建一个缺省的工作(worker)线程,它独立于应用程序主线程来执行所有发送到OnStartCommand方法的intent。
创建一个工作队列,每次向你的OnHandleIntent()传入一个intent,这样你就永远不必担心多线程问题了。
在处理完所有的启动请求后,终止服务,因此你就永远不需调用StopSelf方法了。
提供缺省的OnBind()实现代码,它返回null。
提供缺省的OnStartCommand()实现代码,它把intent送入工作队列,稍后会再传给你的OnHandleIntent()实现代码。
以上所有步骤将汇成一个结果:你要做的全部工作就是实现OnHandleIntent()完成客户端提交的任务。(当然你还需要为服务提供一小段构造方法。)
2、实现OnHandleIntent方法
实现IntentService请求的代码很简单,你要做的工作就是在自定义的继承自IntentService类中重写OnHandleIntent()方法即可,它会自动接收每个启动请求的intent,然后自动在后台完成Intent请求的工作。
下面的代码演示了如何重写OnHandleIntent()方法:
[Service] [IntentFilter(new string[]{"com.xamarin.DemoIntentService"})] public class DemoIntentService: IntentService { public DemoIntentService () : base("DemoIntentService") { } protected override void OnHandleIntent (Android.Content.Intent intent) { Console.WriteLine ("perform some long running work"); Console.WriteLine ("work complete"); } }
继承自IntentService的类与继承自Service的自定义类的区别是:继承自IntentService的类需要通过构造函数传递给基类一个字符串,该字符串的作用是标识内部工作线程。
从内部实现代码上来看,IntentService实际上就是把每个Intent发送的请求都放到一个工作队列中,然后分别在不同的线程中处理工作队列中的每个请求,由于这些Intent都是在与主线程不同的单独线程中运行的,当然不会阻止主线程的运行。
当某个Intent处理完后,IntentService会立即自动调用StopSelf方法停止这个Intent。
总之,利用IntentService,我们既不需要在服务中去显式创建单独的线程,也不需要在重写的Ondestroy方法中终止自己创建的线程,这一些都由IntentService类去自动实现,你只需要关注在服务中实现的功能就行了。
运行截图
主要设计步骤
(1)添加ch1603_Main.axml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:id="@+id/ch1603StartService" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="启动服务" /> <Button android:id="@+id/ch1603StopService" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="停止服务" /> </LinearLayout>
(2)添加ch1603ServiceDemo.cs
using System; using Android.App; using Android.Content; using Android.OS; using Android.Widget; using System.Threading; namespace MyDemos.SrcDemos { [Service] [IntentFilter(new string[] { action })] public class ch1603ServiceDemo : IntentService { public const string action = "MyDemos.ch1603Service"; public ch1603ServiceDemo() : base("ch1603ServiceDemo") { } protected override void OnHandleIntent(Intent intent) { var myHandler = new Handler(MainLooper); myHandler.Post(() => { Toast.MakeText(this, "服务已启动", ToastLength.Short).Show(); }); for (int i = 1; i <= 10; i++) { var msg = string.Format("这是来自服务的第{0}个消息", i); Thread.Sleep(TimeSpan.FromSeconds(4)); myHandler.Post(() => { Toast.MakeText(this, msg, ToastLength.Short).Show(); }); } } public override void OnDestroy() { base.OnDestroy(); new Handler(MainLooper).Post(() => { Toast.MakeText(this, "服务已停止", ToastLength.Short).Show(); }); } } }
(3)添加ch1603MainActivity.cs
using Android.App; using Android.Content; using Android.OS; using Android.Widget; namespace MyDemos.SrcDemos { [Activity(Label = "ch1603MainActivity")] public class ch1603MainActivity : Activity { protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.ch1603_Main); var start = FindViewById<Button>(Resource.Id.ch1603StartService); start.Click += delegate { StartService(new Intent(ch1603ServiceDemo.action)); }; var stop = FindViewById<Button>(Resource.Id.ch1603StopService); stop.Click += delegate { StopService(new Intent(ch1603ServiceDemo.action)); }; } } }