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();
}
}
扫描关注我的微信公众号: