Service為安卓四大元件之一,學會使用service是作為一個優秀的程式員必備的技能。Service運作在主線程之中,可以在Activity界面銷毀的時候依然在背景運作。不能直接在Service裡面直接進行耗時的操作,會導緻ANR。Service有兩種,一種是遠端服務,一種是本地服務。遠端服務指的是不同程序間通信的服務(一般情況下也可以了解為一個App就是一個程序),本地服務是在同一個程序間通信的服務。Service的啟動方式有兩種,一種是在Activity裡面使用startService(),另一種在Activity裡面使用BindService()。需要在Manifest檔案裡面注冊,如果不注冊雖然不報錯但是無法啟動Service。使用BindService()啟動需要在必要的時候調用unbindservice(),不然報異常。Service也可以運作在前台,提高其優先級别,使其不容易被系統殺死。本文将Service的使用示範一遍,最後做一個Demo實作天氣的查詢(天氣資料來源于Weather.com)
Service使用場合:
1.一個或多個Activity需要向同一應用中的Service發出執行某一操作的指令。
2、當界面銷毀時還需要在背景操作任務,比如播放音樂,下載下傳資料等,重新進入的時候還能控制進度的時候。
Service與Thread的差別:
有很多人以為Service是一個線程,這個是錯誤的,因為Service就運作在主線程中,打開一個Service并不是開了一個新的線程。Service中也不能做耗時操作,否則會導緻ANR(彈出應用程式無響應)。Thread是單獨的開一個線程,可以在這個線程中做耗時的操作,不過在這個線程中不能操作UI,而在Service裡可以操作UI。那麼為什麼要弄一個Service 呢?我覺得主要是為了在Activity銷毀的時候app還能繼續工作,并且在Activity重新建立的時候還能控制其啟動的Service,而如果是Thread的話當界面銷毀再次進入的時候就無法控制thread了。
生命周期:
start方式啟動:oncreate()-->onstartcommand()-->onstart()-->onstop()-->ondestroy()
bind方式啟動:oncreate()--->onbind()-->unbind()--->ondestroy();
使用步驟:
1.建立一個類WeatherService繼承
2.在manifest檔案裡面注冊
3.使用對應的啟動方式啟動Service
先來看效果:
因為涉及到網絡的操作,本來想着定義一個回調接口傳回資料,可是怎麼都無法成功擷取資料,最後隻能用廣播的形式把Service擷取的資料傳回給Activity。
在MainActivity中:
@Override
protected void onResume() {
super.onResume();
// 單綁定成功的時候調用這裡
sc = new ServiceConnection() {
// 與服務斷開連接配接
@Override
public void onServiceDisconnected(ComponentName name) {
}
// 與服務連接配接上了
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 強轉為Mybinder
}
};
// 注冊一個廣播接收資料
broadcast = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
json = intent.getStringExtra("result");
ParseJson();
}
};
registerReceiver(broadcast, new IntentFilter("com.xinxue.RESULTBROADCAST"));
}
在Service中:
public class WeatherService extends Service {
private String TAG = "WeatherService";
public String result;
private MyBinder binder;
private String city;
private String code;
// 綁定
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "onBind");
city = intent.getStringExtra("city");
downLoad();
return binder;
}
public class MyBinder extends Binder {
public WeatherService getService() {
return WeatherService.this;
}
// 下載下傳資料
public String getResult() {
return result;
};
}
@Override
public boolean onUnbind(Intent intent) {
Log.e(TAG, "onUnbind");
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
Log.e(TAG, "onRebind");
super.onRebind(intent);
}
// 建立
@Override
public void onCreate() {
Log.e(TAG, "onCreate");
binder = new MyBinder();
super.onCreate();
}
// 啟動
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand");
city = intent.getStringExtra("city");
downLoad();
return super.onStartCommand(intent, flags, startId);
}
@Override
public boolean stopService(Intent name) {
Log.e(TAG, "stopService");
return super.stopService(name);
}
@Override
public void onDestroy() {
Log.e(TAG, "onDestroy");
super.onDestroy();
}
// 開一個線程去下載下傳
private void downLoad() {
try {
code = URLEncoder.encode(city, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
new Thread(new Runnable() {
@Override
public void run() {
String url = "http://op.juhe.cn/onebox/weather/query?cityname=" + code
+ "&key=0e9d91775e452d72d89dbf40d197cd2a";
result = HttpUtils.httpGet(url);
Intent intent = new Intent();
intent.setAction("com.xinxue.RESULTBROADCAST");
intent.putExtra("result", result);
sendBroadcast(intent);
}
}).start();
}
}
掃描關注我的微信公衆号:
示例下載下傳:
去下載下傳咯~~