服务是程序后台的解决方案。服务不依赖于任何用户界面,而是依赖一开始创建它的程序。
多线程编程
和java中一样,多线程的实现方式有两种,一种是继承Thread类,一种是实现Runnable方法。
利用异步处理在子线程中进行UI操作
首先在子线程中,发送一个消息Message,然后通过Handler对消息进行处理。这样就能在子线程中使用UI界面了。
private Handler handler = new Handler(){
public void handleMessage(Message msg){
switch (msg.what){
case UPDATE_TEXT:
text.setText("Nice to meet you");
break;
default:
break;
}
}
};
public void run() {
Message message = new Message();
message.what = UPDATE_TEXT;
handler.sendMessage(message);
}
异步消息处理机制
message:
线程之间传递消息,只能携带少量消息。
Handler:
处理器,通过sendMessage方法发送的消息经过一系列辗转之后会回到handlerMessage()。
MessageQueue:
消息队列,每个线程只有一个消息队列,消息队列存放Handler发送的消息。
Looper:MessageQueue,调用loop方法,发现消息队列中有消息就交给handlerMessage处理。
整个异步消息处理的流程,首先在主线程中重写Handler的handlerMessage方法,当子线程中需要UI处理的时候,新建一个Message对象,通过sendMessage对象,存放在子线程的MessageQueue中,Loop会一直尝试从MessageQueue取出message通过回调方法交给Handler的handleMessage()处理。
AsyncTask
对异步消息处理的封装,AsyncTask是一个抽象类,需要制定3个泛型,第一个是指定的是需要传递的参数,第二个是进度的类型,第三个是返回值的类型。我们需要对AsyncTask中的方法进行重写。
onpRreExecute():在后台任务开始前调用,会进行一些初始化处理。
doInBackgrouds(Params):里面的任务都会通过子线程来执行,进行一些耗时的任务,可以通过publishProgress()来显示进度。
onProgressUpdate() 会根据后台穿过来的数据对progress的状态进行更新。
onPostExecute(Result) 在AsyncTask完成,并返回结果的时候进行调用。
服务
继承Service类,实现相关的方法,通过Context的startService(),stopService()传入意图Intent就能开始和结束服务。
服务和活动的通信
主要通过onBind方法来实现,该方法需要返回一个binder实例。当活动和服务绑定的时候就会执行binder中的方法。
首先需要创建一个匿名内部类ServiceConnection:
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
downloadBinder = (MyService.DownloadBinder)service;
downloadBinder.startDownload();
downloadBinder.getProgress();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
然后在点击事件内通过bindService()实现绑定,需要三个参数,第一个参数是Intent,第二个参数是ServiceConnection,第三个参数是一个标识位,表示绑定之后自动开始服务。
case R.id.bind_service:
Intent bindIntent = new Intent(this,MyService.class);
bindService(bindIntent,connection,BIND_AUTO_CREATE);
break;
case R.id.unbind_service:
unbindService(connection);
break;
服务的生命周期
可以通过Context的startService方法开启一次服务, 如果是第一次开启服务,onCreate会先于于OnStartCommand执行,不管启动多少次startService,只要调用一次stopService或者stopSelf方法,服务就会停止。
还可以通过Context的bindService()来开启一次服务,这时就会回调onBind()方法,如果这个服务之前没有创建过,那么onCreate方法就会先于onBind方法执行。使用unBind来停止一次服务。
如果同时启动了startService和bindService,那么只有同时unBind,和stopService才能使服务停止。
使用前台服务
由于系统服务的优先级很低,因此我们可以使用前台服务。使用startForeground可以将赋予转化为前台服务,第一个参数是标识id,第二个参数是构建的Notification。
使用IntentService
构建服务需要手动开启线程并停止,Android提供了一个自动停止的服务IntentService。IntentService会自动开启子线程执行onHandleIntent,并在完成后调用onDestroy销毁服务。