Integer是Java中的wrapper type(reference type)!
簡單地說它是一個類別,每當你使用它一次就會有一個新的object產生!
因為所有的wrapper type 都屬於immutable的!
拿String的例子來說,
String strA = "hi";
strA = "hello";
上面這個例子實質上在記憶體裡面是有2個object產生!
因為他是immutable!
Integer也是一樣!
但這篇要講的是Integer的一個pool機制!
pool機制是為了效能所存在!
直接從下面的例子來看
Integer iA = 100;
Integer iB = 100;
System.out.println(iA==iB); // true
Integer iA = 128;
Integer iB = 128;
System.out.println(iA==iB); // false
Integer iA = new Integer(100);
Integer iB = new Integer(100);
System.out.println(iA==iB); // false
int iA = 128;
int iB = 128;
System.out.println(iA==iB); // true
大家可能會覺得奇怪,為什麼第二個範例和第三個會是false
因為對於wrapper type來說,使用==符號比較的話,是在比較其記憶體位址!!!
並不是在比較value!
那大家可能也會覺得奇怪,那為什麼第一個就是true?
因為Integer有一個pool機制(String也有pool機制)!
而這個pool裡面存放的value為-128~127!
也就是說當value在-128~127之間的話,都會從pool中存取,
並不會重新產生一個object!
那大家可能也會覺得那麼第三個例子為什麼是false?
value是100阿!有在pool範圍內!
那是因為已經使用new了!竟然使用new,就會配置一塊新的記憶體給它!
第四個範例的value超過pool了,
但結果還是true的原因是因為第四個範例並不是wrapper type!
而是primitive type!
primitive type的比較符號==就是在比value!
那麼可能有人會好奇什麼時候使用int或Integer,
恩,Integer他是屬於類別,因此他會有比較fancy的method使用,
當你可能得對你的value做一些較複雜的操作時或許就可以使用Integer!
還有就是當你有使用Collection時,
記得請使用wrapper type!
雖然說java目前都有支援
auto-boxing的機制,儘管你傳入primitive,
java都會幫你轉成wrapper type!
但這個轉換的機制是很會消耗效能的!
因此在這種情況也請使用wrapper type!
上面有提到String也有pool機制,
但String pool並沒有範圍限制!
只要你使用過的String都會被放置在pool之中!
先前講過arduino的基本介紹,
這篇要講如何綁上bluetooth shield到arduino上面!
首先要先介紹bluetooth shield上的pin腳,
先看到下圖,下圖中右邊有一排pin腳,
主要會用到前面4隻pin腳,
而4隻pin腳依序為:
- 5V:供電的(+)
- TX:傳送訊號
- RX:接收訊號
- GND:接地線(-)
而arduino板上也一定會有上述對應的pin腳,
基本上都插上去就可以,
不過有一點比較特別,
在於RX/TX的點,
Arduino板上的TX要接到Bluetooh shield上的RX,
Arduino板上的RX反而接到Bluetooth shield上的TX,
可以看到參考下面的表,
Arduino | Bluetooth Shield |
RX | TX |
TX | RX |
5V | 5V |
GND | GND |
對了,基本上arduino板上的RX/TX都是預設pin0和pin1!
至少uno和duemilanove這兩塊板子上都是!
所以就差在對應上的pin0和pin1吧!
(當然你也可以插在別的pin腳上,但是在寫code時就得稍為設定)
差上去以後,基本上你的bluetooth shield會一直閃紅燈,
一直閃一直閃,直到有人連結上這台bluetooth上,紅燈才會恆亮!
接著來寫個sample測試!
int iLedPin = 13;
void setup(){
// define the PIN as OUTPUT
pinMode(iLedPin ,OUTPUT);
// using baud rate 9600 to listen.
Serial.begin(9600);
}
void loop(){
while (Serial.available()){
char cCmd = Serial.read();
if (cCmd =='o'){
digitalWrite(iLedPin,HIGH);
}else if (cCmd == 'c'){
digitalWrite(iLedPin,LOW);
}
}
}
把上述的code deploy進去arduino以後,
就可以用你的電腦來測試了!
不管你是windows,osx,linux,只要你的OS連接到藍牙以後,
都會被模擬成serial port!
所以如果你用的是linux或者mac,
你會發現在你的/dev/底下多了一個device,
像我的就是/dev/tty.KENarduino-DevB,
那麼就可以用下列的指令連結到你的藍牙了,
sudo cu -s 9600 -l /dev/tty.KENarduino-DevB
如果連結成功應該會在你的terminal上看到下列字樣
Connected
那麼就代表你成功連結到藍牙裝置,就可以透過藍牙下指令給arduino了!
最後可以試著輸入o和c,然後觀察你的pin13那顆led有無變化!
PS:如果你用的是windows,直接去載putty吧!透過putty去連結藍芽,只要輸入你的藍牙是COM幾就可以連線!
這篇要說明
這兩者的差別!
其實在我之前的筆記有關
Service的文章,都是使用startService!
並沒有使用bindService!
一方面是因為startService簡單很多!
再來也是最近才發現有bindService!
應該是說我原本以為startService的行為與bindService差不多!
但實際找答案以後才知道不是這樣的!
這裡就不多作說明如何使用startService或者bindService!
主要會說明這兩者差異性!
如果要看如何使用可以看之前的筆記:
- Android C2DM (四):實作之Android篇
- android detect screen on and screen off
- android 偵測 sdcard
先去看Google的定義,對於startService,Google定義如下
Once started, a service can run in the background indefinitely, even if the component that started it is destroyed. Usually, a started service performs a single operation and does not return a result to the caller. For example, it might download or upload a file over the network. When the operation is done, the service should stop itself.
簡言之用startService啟動,這個service是不會跟隨著啓動他的component消滅!且原則上是不能與UI互動的!(原則上)
而對於bindService,定義如下:
A bound service offers a client-server interface that allows components to interact with the service, send requests, get results, and even do so across processes with interprocess communication (IPC). A bound service runs only as long as another application component is bound to it. Multiple components can bind to the service at once, but when all of them unbind, the service is destroyed.
用bindService起來的話,則此service可以跟該component進行溝通!甚至可以做到 IPC!
小結:
bindService和startService最主要的差異在於其本身的lifecycle!
以及bindService可以用來做IPC!簡單的說就是可以讓你的service和UI溝通!
這裡就用一個project來說明吧!
先建立一個new project!
在這project中建立一個Activity,並指定它為launcher!
然後在建立一個Service!內如如下:
public class Services extends Service {
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.d("TestService","onBind");
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("TestService","onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public ComponentName startService(Intent service) {
Log.d("TestService","startService");
return super.startService(service);
}
@Override
public void onCreate() {
super.onCreate();
Log.d("TestService","onCreate");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("TestService","onDestroy");
}
@Override
public boolean onUnbind(Intent intent) {
Log.d("TestService","onUnbind");
return super.onUnbind(intent);
}
}
可以看到上面的Service中並沒有做任何處理!
只有簡單的Log!
目的只是要讓我們瞭解startService和bindService的lifecycle差異性!
首先先來講startService,
我們先在onCreate中start!如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startService(new Intent(this,Services.class));
}
然後按下run,在開啟DDMS來觀看log!
會發現印出了”onCreate"->"onStartCommand"!
這時候按下back鍵來destroy這個activity,你會發現什麼都沒有印出來!
也就是說這個service仍在background執行!(你得手動stop)
這時候我們換成bindService來看看,如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bindService(new Intent(this,Services.class),null,Context.BIND_AUTO_CREATE);
}
一樣按下run!再看一下LOG!
會發現印出“onCreate"->"onBind"!
再按下back鍵,會發現...印出了!
“onUnbind"->"onDestroy"
總結上面兩項的差異,
會發現使用bindService時,
這個service的lifecycle是跟隨著bind它的object!
所以當該object被destroy,自然而然這個service也被destroy!
而使用startService,
就不是這樣了!這個service就是獨立的!不屬於任何一個object!
得靠stopService來停止!(任何一個Activity中都可以stop)
註:bindService的使用方式比較特別!
多帶了幾個參數!
在這個例子我們第二個參數設為null!
其實這參數是要傳入一個ServiceConnection的物件!
而ServiceConnection是一個Interface,這個Interface中
會有兩個callback function!
主要是用來monitor 這個service的state!