Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> osgi之ServiceListener的應用

osgi之ServiceListener的應用

編輯:關於Android編程

前言

我原想直接跳過這些osgi中基礎知識,直接從osgi應用的一些中級篇或者高級篇開始的,後來想到osgi中的ServiceListener、ServiceTracker、Ds還是都需要講一下,所以決定將osgicommand後續中的內容放一下,從ServiceListener開始講一下,不過這裡就不再講述felix官網中的ServiceListener的example,而是自己單獨編寫example和進行相關講解。


ServiceListener

/**
 * A {@code ServiceEvent} listener. {@code ServiceListener} is a
 * listener interface that may be implemented by a bundle developer. When a
 * {@code ServiceEvent} is fired, it is synchronously delivered to a
 * {@code ServiceListener}. The Framework may deliver
 * {@code ServiceEvent} objects to a {@code ServiceListener} out
 * of order and may concurrently call and/or reenter a
 * {@code ServiceListener}.
 * 
 */

ServiceListener解釋如上所示,本義就是這只是一個接口,在進行相應的實現之後,可以用來監控某些服務,在服務注冊、修改、注銷的時候,進行相應的其他調用,現在我將講述這個ServiceListener的具體使用,在使用過程中,再來講解中間會有那些問題。


ServiceListener用法1

先分別提供一個接口和一個實現類,分別為HelloService和HelloServiceImpl,代碼如下:

HelloService:

package cn.com.example;

/**
 * Created by xiaxuan on 16/7/12.
 */
public interface HelloService {

    String hello(String name);
}

HelloServiceImpl:

package cn.com.example;

/**
 * Created by xiaxuan on 16/7/12.
 */
public class HelloServiceImpl implements HelloService {

    public String hello(String name) {
        return "hello " + name;
    }
}

都很簡單,就是提供一個簡單的服務,其中有一個方法為hello,真正的重點還是在Activator中,現在先貼出Activator中的代碼,隨後再來講解其中監聽服務和容易出現的問題:

package cn.com.example;

import org.osgi.framework.*;

/**
 * Created by xiaxuan on 16/7/12.
 */
public class Activator2 implements BundleActivator, ServiceListener {

    ServiceRegistration serviceRegistration;
    BundleContext context;


    public void start(BundleContext context) throws Exception {
        this.context = context;
        context.addServiceListener(this);
        System.out.println("service registered....");
        serviceRegistration = context.registerService(HelloService.class, new HelloServiceImpl(), null);
    }

    public void stop(BundleContext context) throws Exception {
        context.removeServiceListener(this);
        System.out.println("service unregistered...");
        serviceRegistration.unregister();
    }

    public void serviceChanged(ServiceEvent event) {
        switch (event.getType()) {
            case ServiceEvent.REGISTERED:
                //獲取service引用
                ServiceReference ref  = context.getServiceReference(HelloService.class);
                //獲取service實例
                HelloService helloService = (HelloService) context.getService(ref);
                if (helloService != null) {
                    //調用service方法
                    System.out.println(helloService.hello("xiaxuan"));
                    //釋放service
                    context.ungetService(ref);
                }
                break;
            case ServiceEvent.UNREGISTERING:
                System.out.println("serviceChanged find service unregistered.");
                break;
        }
    }
}

我們在Activator中實現ServiceListener之後,還需要將自己本身加入到監聽器中,在serviceChanged方法中,當服務出現變化的時候可以在這個方法中監聽到,其中或是注冊,注銷,或是修改都可以做出監聽,現在我們打上斷點,監聽相關服務。


服務啟動

服務啟動過程就不再截圖了,這次我們在stop bundle,然後再start bundle的時候再來調試和查看相應的信息,現在展示karaf已經成功啟動的截圖,如下所示:
這裡寫圖片描述
可以看到example這個Bundle已經正常啟動,現在先使用stop命令,實質上在karaf中這個命令是Bundle:list命令,在karaf中大量的運用命令,在之後若有時間將會講一下karaf的源碼,講一下這些命令,這個時候example的id為8,我們使用stop 8停止這個Bundle,執行命令之後如下所示:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxoMiBpZD0="title">這裡寫圖片描述

當Bundle中的state為resolved的時候,這個Bundle已經停止下來了,然後我們再啟動Bundle,命令為start 8,這個時候我們觀察我們的斷點,這個斷點設置在serviceChanged方法中,如下所示:

這裡寫圖片描述

我們放開斷點,這個時候程序再次進入斷點,如下:
這裡寫圖片描述

發現這次進入斷點的時候,event類型和上次有所不同,說明這裡的ServiceListener的serviceChange方法對當前bundle啟動的手,所有的服務注冊都做了監聽,這個時候,我們去掉斷點,觀察控制台,會發現打了許多次的’hello xiaxuan’,如下:

這裡寫圖片描述

打了五次的hello xiaxuan,說明有五次的服務注冊,每一次服務注冊都進來獲取了一次HelloService,然後調用了一次服務,在控制台打印一次,ServiceListener並沒有對具體某個服務進行監聽。


ServiceListener用法2

在以上ServiceListener的用法中,並不僅是在Activator中實現ServiceListener來做到監聽服務,可以在start方法中直接實現,如果Activator類實現ServiceListener接口,還需要將本身加進Listener中,代碼如下:

context.addServiceListener(this);

如果在start方法中實現的話,代碼如下所示:

package cn.com.example;

import org.osgi.framework.*;

/**
 * Created by xiaxuan on 16/7/13.
 */
public class Activator3 implements BundleActivator {

    ServiceRegistration serviceRegistration;
    BundleContext context;


    public void start(BundleContext bundlecontext) throws Exception {
        this.context = bundlecontext;
        System.out.println("service registered....");
        serviceRegistration = context.registerService(HelloService.class, new HelloServiceImpl(), null);
        context.addServiceListener(new ServiceListener() {
            public void serviceChanged(ServiceEvent event) {
                switch (event.getType()) {
                    case ServiceEvent.REGISTERED:
                        //獲取service引用
                        ServiceReference ref  = context.getServiceReference(HelloService.class);
                        //獲取service實例
                        HelloService helloService = (HelloService) context.getService(ref);
                        if (helloService != null) {
                            //調用service方法
                            System.out.println(helloService.hello("xiaxuan"));
                            //釋放service
                            context.ungetService(ref);
                        }
                        break;
                    case ServiceEvent.UNREGISTERING:
                        System.out.println("serviceChanged find service unregistered.");
                        break;
                }
            }
        });
    }

    public void stop(BundleContext context) throws Exception {
        System.out.println("service unregistered...");
        serviceRegistration.unregister();
    }
}

直接在addServiceListener中new ServiceListener,然後實現相關方法,相比較而言還簡單一點,不過實現的效果相同。


總結

使用ServiceListener時,只在Service發生相關變更的時候獲取開銷,可以動態感知service的注冊和注銷。

但是問題在於在ServiceListener注冊之前已經存在的Service無法監聽到,需要自己維護service的獲取和釋放,如果需要監聽多個service的話,十分不方便。

只要是服務發生變更的時候就進行相關監聽,其實在許多時候無需監聽其他服務,有時候用起來比較麻煩。

下一節中將講解ServiceTracker,這是對ServiceListener的進一步封裝,能夠有效的監聽我們所需的服務。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved