編輯:關於Android編程
一:Service的概述
Service是Android四大組件中與Activity最相似的組件。都代表執行的程序,Service與Activity的區別在於:
Service一直在後台運行,它沒有用戶界面,所以絕不會到前台來。一旦Service被啟動起來之後,它就與Activity一樣。完全具有自己的生命周期。
關於程序中Activity和service的選擇標准:
如果某個程序組件需要在運行時向用戶呈現某種界面,或者該程序需要與用戶交互,就需要使用Activity,否則就應該考慮使用Service了。
如:下載東西,播放音樂。可以一邊下載,一邊播放,一邊玩其他的事情。但是Activity是無法做到的。只要Activity被關閉或者最小化了,程序就停止了。
二:特點
1.沒有UI
2.進行耗時較長或者與用戶沒有交互的一些功能
3.Service具有較高的優先級,比stop的Activity優先級要高,最高的優先級是前台Activity
4.具有較長的生命周期
三:Service的使用
1)創建:
創建類繼承Service,實現OnBind()方法。
Service與Activity都是從Context派生出來的。
因此可以使用Context中的方法,如getResouces()等方法。
2)配置:
在配置文件中配置標簽
設置android:name屬性,也可以配置元素
3)啟動:
Service啟動依賴於其他組件,可以使用Activity或者Receiver等作為調用者,調用者可以使用以下兩種形式啟動Service
(1)startService
startService啟動Service涉及生命周期方法:
onCreate()–onStartCommand()/onStart()–onDestory()
a)onCreate()創建Service實例時的回調函數,啟動的Service實例如果不存在會觸發一次之後不會觸發.
b)onStartCommand() 啟動Service時的回調函數每次啟動都會觸發,可以通過參數startId獲取其啟動次數,第二個參數flags表示啟動服務的方式:
c)onStart():啟動Service時,已經被淘汰了。
d)onDestory():銷毀Service實例
注意:
onStartCommand()的返回值用來指定Service的系統在用戶為手動關閉Service前自動回收Service資源了Service資源情況下的重啟行為:
a)START_STICKY
如果service進程被kill掉,保留service的狀態為開始狀態,但不保留遞送的intent對象。隨後系統會嘗試重新創建service,由於服務狀態為開始狀態,所以創建服務後一定會調用onStartCommand(Intent,int,int)方法。如果在此期間沒有任何啟動命令被傳遞到service,那麼參數Intent將為null。
b)START_NOT_STICKY
“非粘性的”。如果在執行完onStartCommand後,服務被異常kill掉,系統不會自動重啟該服務。
c)START_REDELIVER_INTENT
使用這個返回值時,如果在執行完onStartCommand後,服務被異常kill掉,系統會自動重啟該服務,並將Intent的值傳入。
d)START_STICKY_COMPATIBILITY:
START_STICKY的兼容版本,但不保證服務被kill後一定能重啟。
該方法用來啟動一個獨立的Service實例, 該實例與調用者沒有關聯關系 調用者的生命周期不會影響到Service的生命周期 即使訪問者退出了,Service仍然運行。
(2)bindService
該方法用來將一個Service實例與調用者建立關聯關系,Service與調用者之間可以進行數據共享,調用者聲明周期會影響的Service的生命周期,即使訪問者退出了Service也就終止
bindService方法有三個參數:
第一個參數包含要綁定Service信息的Intent對象
第二個參數是一個ServiceConnection對象,該對象用於監聽訪問者與Service之間的連接情況。當訪問者與Service之間鏈接成功時將回調該ServiceConnection對象的onServiceConnected(ComponentName,IBinder)方法;當Service所在的宿主進程由於異常中止或由於其他原因終止,導致該Service與訪問者之間斷開連接時回調該ServiceConnection對象的onServiceDisconnected(ComponentName)方法。其中onServiceConnected方法中的IBinder對象,可實現與被綁定Service之間的通信。在開發Service類時,該Service類必須提供一個IBinder onBind()方法,該方法所返回的IBinder對象將會傳給ServiceConnection對象裡onServiceConnected方法的參數中。這樣訪問者就
可以通過該IBinder對象與Service進行通信。實際開發時通常會采用繼承Binder(IBinder的實現類)的方式實現自己的IBinder對象。
第三個參數指定綁定時是否自動創建Service
(如果Service還未創建),該參數可指定為0(不自動創建)
或BIND_AUTO_CREATE(自動創建)。
bindService啟動Service的生命周期方法: onCreate()--->onBind()--->onUnbind()--->onDestory().
a)onCreate() 同startService
b)onBind() 在Service與調用者建立關聯關系時使用,該方法會返回一個IBinder類型的實例給調用者,作為Service在調用者的代理.
c)onUnbind() Service與調用者解除綁定。
d)onDestory() 同startService
e)onRebind() 重新連接
5)停止:針對不同啟動方式,可以使用兩種方式在調用者中手動關閉Service
stopService(Intent it);
unbindService(ServiceConnection conn)
6)IntentService
Android中的Service是用於後台服務的,當應用程序被掛到後台的時候,問了保證應用某些組件仍然可以工作而引入了Service這個概念,那麼這裡面要強調的是Service不是獨立的進程,也不是獨立的線程,它是依賴於應用程序的主線程的,也就是說,在更多時候不建議在Service中編寫耗時的邏輯和操作,否則會引起ANR(Application Not Responding)。那麼我們當我們編寫的耗時邏輯,不得不被service來
管理的時候,就需要引入IntentService,IntentService是繼承Service的,那麼它包含了
Service的全部特性,當然也包含service的生命周期,那麼與service不同的是,IntentService在執行onCreate操作的時候,內部開了一個線程,去你執行你的耗時操作。該線程保證同一時刻只處理一個Intent.這樣IntentService不會阻塞主線程。
IntentService的使用和Service是類似。它需要重寫onHandleIntent(Intent intent)方法。
注意:service 沒有unbind時was originally bound here錯誤。
在程序中,如果在activity中綁定了服務,
而沒有在destory中,寫unbind,會出現這種異常,
解決方式:在Activity的onDestory方法中調用unbindService(sc)
方法,該方法是context中的方法。
package com.xspacing.service;
import com.xspacing.service.SecondService.MyBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
public class MainActivity extends Activity {
private Intent intent;
private Intent intent2;
private BindServiceConnection conn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startService(View v) {
intent = new Intent(this, FirstService.class);
// 啟動服務
// 通過這個方式啟動的服務,這個服務的生命周期不受activity的生命周期的影響
startService(intent);
}
public void stopService(View v) {
stopService(intent);
}
public void startBindService(View v) {
intent2 = new Intent(this, SecondService.class);
conn = new BindServiceConnection();
// 通過這個方式啟動的服務,這個服務的生命周期與activity的生命周期息息相關的
bindService(intent2, conn, BIND_AUTO_CREATE);
}
public void stopBindService(View v) {
// stopService(intent);
unbindService(conn);
conn=null;
}
public void intentService(View v) {
Intent intent = new Intent(this, MyItentService.class);
startService(intent);
}
class BindServiceConnection implements ServiceConnection {
private static final String TAG = "BindServiceConnection";
// service與activity進行綁定的時候會回調
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "onServiceConnected()");
MyBinder binder=(MyBinder) service;
int count = binder.getCount();
Log.i(TAG, count+"");
}
// service與activity異常解除綁定的時候會回調
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "onServiceDisconnected()");
}
}
@Override
protected void onDestroy() {
if (conn != null) {
unbindService(conn);
}
super.onDestroy();
}
}
package com.xspacing.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
/**
* @ClassName FirstService.java
* @Description Service生命周期
* @author smile
* @version v1.0
* @date 2016年10月8日
*/
public class FirstService extends Service {
private static final String TAG = "FirstService";
private boolean flag;
private int count;
@Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* 開啟了再開啟只執行一次
*/
@Override
public void onCreate() {
Log.i(TAG, "onCreate()");
flag = true;
new Thread(new Runnable() {
@Override
public void run() {
while (flag) {
count++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG, count + "");
}
}
}).start();
super.onCreate();
}
/**
* 開啟了再開啟每次執行一次
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand()");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy()");
flag = false;
super.onDestroy();
}
}
package com.xspacing.service;
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
public class MyItentService extends IntentService {
private static final String TAG = "MyItentService";
private int count;
private boolean flag = true;
public MyItentService(String name) {
super(name);
}
public MyItentService() {
this("MyItentService");
}
/**
* 底層開辟了一個子線程
*/
@Override
protected void onHandleIntent(Intent intent) {
while (flag) {
count++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG, count + "");
}
}
@Override
public void onDestroy() {
flag = false;
super.onDestroy();
}
}
package com.xspacing.service;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class SecondService extends Service {
private static final String TAG = "SecondService";
private int count;
boolean flag;
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate()");
Log.i(TAG, "onBind()");
flag = true;
new Thread(new Runnable() {
@Override
public void run() {
while (flag) {
count++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG, count + "");
}
}
}).start();
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind()");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy()");
flag = false;
super.onDestroy();
}
// 通常自己實現一個類繼承Binder,也間接地實現了IBinder接口
public class MyBinder extends Binder {
public int getCount() {
return count;
}
}
}
自定義View實現 “手機淘寶”物流進程模塊進度告知UI橫向版
這些天都在浪幾乎沒撸代碼,然後今天下午找了個下午茶時間捯饬了個自定義View來實現 很多APP都有卻沒怎麼公開的一個“進度通知的View”實現po
Android圖片緩存處理
LruCache以鍵-值對的形式存儲(內部定義了一個LinkedHashMap)數據,通過new LruCache(int size)實例化,參數使指定分配給LruCac
Android UI組件進階(1)——帶進度條的按鈕
Android UI組件進階(1)——帶進度條的按鈕 本節引言: 這個系列是繼Android UI組件實例大全後的進階
android:Notification實現狀態欄的通知
在使用手機時,當有未接來電或者新短消息時,手機會給出響應的提示信息,這些提示信息通常會顯示到手機屏幕的狀態欄上。Android也提供了用於處理這些信息的類,它們是Noti