編輯:關於Android編程
我原想直接跳過這些osgi中基礎知識,直接從osgi應用的一些中級篇或者高級篇開始的,後來想到osgi中的ServiceListener、ServiceTracker、Ds還是都需要講一下,所以決定將osgicommand後續中的內容放一下,從ServiceListener開始講一下,不過這裡就不再講述felix官網中的ServiceListener的example,而是自己單獨編寫example和進行相關講解。
/**
* 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的具體使用,在使用過程中,再來講解中間會有那些問題。
先分別提供一個接口和一個實現類,分別為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的用法中,並不僅是在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的進一步封裝,能夠有效的監聽我們所需的服務。
這麼長時間沒寫博客感覺手都要生了啊,最近因為工作的關系來到了上海,目前還算穩定,所以抓緊時間寫篇博客壓壓驚。標題早已經看穿一切,這次我們來模仿一下
概述android打包過程,下面這張圖取自Android開發權威指南,非常清晰。整個過程使用的工具有 名稱 功能介紹 在操作系統中的路徑 aapt An
1、首先看兩個例子 (1)進程內 Client端 public class CounterService extends Service impleme
Paint與Canvas下面先說下Paint的基本設置函數:paint.setAntiAlias(true);//抗鋸齒功能paint.setColor(Color.RE