Android Service的用法

 最近研究了一个android的service,现在做一下总结。
             其实要了解service,我建议不要去到网上看,因为什么呢。网上好多的写的东西都是你抄我,我抄你,都差不多。我建议直接看android的官方文档,只要仔细看了,差不多都能理解,而且官方文档上面还有一些sample。下面我们来一起总结,我打算从以下几个方面来介绍service,如果有误,请谅解。如果有什么建议,可以给我发邮件: leehong2005@163.com

1、什么是Service
2、Service的生命周期
3、Service与Activity进行交互通信
4、Service Demo

1、什么是Service

             Service就是一个应用程序组件,用来执行一些长时间的操作,然而不与用户交互或者为其他应用程序提供一些功能。每一个Service类都必须定义在AndroidManifest.xml中,以<service> tag开头。如下所示:
              <service android:name="com.lee.demo.service.NetworkService">
                     <intent-filter>
                            <action android:name="com.lee.demo.service.networkservice" />
                            <category android:name="android.intent.category.default" />
                     </intent-filter>
              </service>
             注意Services,它与其它应用程序对象一样,运行在当前进程的主线程中,也就是说,如果你的service打算做一些很耗CPU或阻塞的操作(如mp3播放,访问网络等),你应当进一个线程来执行这些工作。
  • 一个Service不是一个单独的进程,服务本身并不暗示它运行在单独的进程之中。它运行在当前进程之中,相当于是这个进程的一部分。
  • 一个Service也不是一个线程,它运行在主线程中,所以如果在服务中做耗时的事情,应该起一个线程,不然就会出现ANR(Applicaton Not Responding)对话框。
  • 如果应用程序想在后台做一些事情,不想与activity进行交互,那么就用Context.startService来启动一个服务,对应关闭的方法就是Context.stopService()
  • 如果activity想与Service交互,比如从Service里取得数据,那么此时就不能用startService,要用Context.bindService方法了,对应停止的方法就是Context.unbindService()。

Service的生命周期

             当在activity里面调用了Context.startService后,系统会得到这个service,然后调用onStartCommand()方法,此时service就是运行起来,直到Context.stopService()或stopSelf()方法被调用。注意,多次调用startService并不会起很多个服务,它好像只有一个实例。不管你调用几次startService,要停止服务,只需要调用stopService或stopSelf一次就行了。
             我们也可以调用Context.bindService来得到一人与service的连接,其实就是得到一个IBinder接口的对象,通过这种方式启动服务的话,是不是会调用onStartCommand()方法了。
             一个服务可以启动,也可以绑定一个连接到它上面,这种情况下,系统会使服务一直运行,只要它被启动了,或者至少有一个到它的连接。如果一个服务被结束的话,它会调用onDestroy()方法,那么所有的清理工作都应当在这个方法里面进行。

             Service分为本地服务(Loacl Service)和远程服务(Remote Service)。
             本地服务:用于应用程序内部,这也与客户端(可以理解也activity)进行通信就很方便。
             远程服务:用于android系统内部的应用程序之间。

Service与Activity进行交互通信

             这里我就用一个例子来说明这个问题。比如,我在一个activity里启动了一个服务,在这个服务里,我从网上下载一张图片,得到一个bitmap,在服务肯定去起一个线程去下载图片,最终我得到了这个bitmap,但是,当下载完了后,我怎么让它显示到activity上面呢? 直接在service启动的线程里去把bitmap设置给ImageView的?行吗?不行,因为在非UI线程里操作UI的东西,会有问题。那要怎么做?
             这里我列出三种方案:
  • 轮循:Activity周期性地去问service,你做完没有,如果做完了,就去取数据。这个方法不是特别好。
  • 回调:之前注册一个回调,当service完成任务后,执行这个回调。
  • Broadcast:当service完成任务后,发送一个广播,任务注册了该广播的receiver都能收到该广播。用registerReceiver来注册一个接受者,发送广播用sendBroadcase()方法。
             我觉得方法2,3是比较好的一种解决方案。我这个例子里用的是方法3,发送一个广播消息。
还有,启动这个service不能用Context.startService,要用Context.bindService,这个方法会得到一个与service的连接。具体的例子,后面再讲。

Service Demo


             这是NetworkService类,它继承于Service类。这里我重新实现了一个Binder,在它里面我实现了getData()这个方法,返回一些数据。onBind()这个方法里,就不能返回null了,应该返回ServiceBinder的对象。

public class NetworkService extends Service
{
             public static final String ACTION_NETWORKSERVICE = "com.lee.demo.service.networkservice";
            private String m_bmpUrl = "http://hiphotos.baidu.com/keyj00/pic/item /816bf9accd05543e4a36d6a6 .jpg";
             private ServiceBinder m_serviceBinder = new ServiceBinder();
             private Bitmap m_bitmap = null;

             public class ServiceBinder extends Binder implements INetworkService
             {
                            @Override
                            public Object getData()
                            {
                                          return m_bitmap;
                            }
             }
     
             @Override
             public IBinder onBind(Intent intent)
             {
                          return m_serviceBinder;
             }
     
             public void onCreate()
             {
                          new Thread(null, new Runnable()
                           {
                                        @Override
                                        public void run()
                                        {
                                                    getBitmapFromNet();
                                       }
                            }, "GetBitmapFromNetwork").start();

                          super.onCreate();
             }
     
             protected void getBitmapFromNet()
             {
                          m_bitmap = BitmapUtility.getBitmapFromNet(m_bmpUrl);
                          if (null != m_bitmap)
                          {
                                        this.sendBroadcast(new Intent(NetworkReceiver.ACTION_RECEIVER));
                          }
             }
             ......
}

             再看看activity里面如何使用这个Service。这里先new一个ServiceConnection类的对象,后面bindService时会用到。

public class NetworkActivity extends Activity
{
             // The receiver to recive broadcase from service.
              private NetworkReceiver m_receiver = new NetworkReceiver();
             private INetworkService m_networkService = null;
     
             private ServiceConnection m_serviceConn = new ServiceConnection()
             {
                          @Override
                          public void onServiceConnected(ComponentName name, IBinder service)
                          {
                                       // 这里先把这个连接保存起来。
                                        m_networkService = (INetworkService)service;           
                          }

                          @Override
                          public void onServiceDisconnected(ComponentName name)
                          {
                          }
             };
     
             public void onCompleteService()
             {
                          if (null != m_networkService)
                          {
                                       // 从Binder中去取数据
                                        Bitmap bmp = (Bitmap)m_networkService.getData();
                                       if (null != bmp)
                                        {
                                                    // ......
                                       }
                          }
             }
     
             protected void onCreate(Bundle savedInstanceState)
            {
                          super.onCreate(savedInstanceState);
                          this.setContentView(R.layout.network_service);
                           this.bindService (new Intent(NetworkService.ACTION_NETWORKSERVICE), m_serviceConn, BIND_AUTO_CREATE);
                           this.registerReceiver (m_receiver, new IntentFilter(NetworkReceiver.ACTION_RECEIVER));
             }
     
             @Override
             protected void onDestroy()
             {
                          this.unbindService(m_serviceConn);
                          this.unregisterReceiver(m_receiver);
                          super.onDestroy();
             }
}

             再看看Receiver如何实现:

public class NetworkReceiver extends BroadcastReceiver
{
             public static final String ACTION_RECEIVER = "com.lee.demo.service.networkreceiver";
     
             @Override
             public void onReceive(Context context, Intent intent)
             {
                          if (context instanceof NetworkActivity)
                          {
                                       // 这里调用activity的方法来操作UI的东西。
                                        ((NetworkActivity)context).onCompleteService();
                          }
             }
}

             以上大概讲了一个service的用法,用startService来启动service的情况比较简单,这里就不讲了,还有远程service有点复杂,我现在还没有研究过多,所以也没法讲。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值