編輯:關於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來實現 很多APP都有卻沒怎麼公開的一個“進度通知的View”實現po
LruCache以鍵-值對的形式存儲(內部定義了一個LinkedHashMap)數據,通過new LruCache(int size)實例化,參數使指定分配給LruCac
Android UI組件進階(1)——帶進度條的按鈕 本節引言: 這個系列是繼Android UI組件實例大全後的進階
在使用手機時,當有未接來電或者新短消息時,手機會給出響應的提示信息,這些提示信息通常會顯示到手機屏幕的狀態欄上。Android也提供了用於處理這些信息的類,它們是Noti