1 多线程实现
Android中,当需要进行一些耗时操作时,常常需要开启一个多线程来进行耗时操作,但是当要进行UI操作时则需要在主线程中进行,因此这就涉及到了进程间的切换.
1.1 异步消息处理机制(Handler)
主线程定义Handler,并重写handlerMessage()方法,当开启一个线程并对其进行耗时操作结束后,要想跳转到主线程进行UI操作时,则需要定义一个Message消息,然后用handler把消息发出去,并在handlerMessage()中进行接收处理,从而实现异步.
解析异步消息处理机制:
- Message:在线程之间传递的消息,可携带少量的信息,在线程之间进行数据交流
- Handler:处理者,用来发送和处理消息
- MessageQueue:消息队列,用来存放所有通过Handler发送的消息,这些消息会被一只存放在消息队列中,等待被处理,每个线程只有一个消息队列
- Looper:是每个消息队列的管家,当调用Looper的loop()方法后,就会进入一个无限循环中,每当发现消息队列中存在一个消息,就会把它取出来,并传递到Handler的handlerMesseage()方法中,进行消息的发出,每个线程中只会有一个Looper对象
1.2 使用AsyncTask
asyncTask是Android提供的一个方便我们在子线程中进行UI操作的工具,它背后实现的原理也是基于异步消息处理机制,只是Android为我们做了一个很好的封装.
使用时继承AsyncTask,并重写相应的方法,如下:
/**
* AsyncTask方便在子线程中执行UI操作,基于异步消息处理机制
* 泛型参数一:执行AsyncTask时需要传递的参数
* 泛型参数二:后台执行任务时,要显示的进度单位
* 泛型参数三:执行完毕后的返回值单位
*/
public class MyDownloadTask extends AsyncTask<String, Integer, Integer>{
/**
* 会在后台任务开始执行前调用,通常用来执行一些界面上的初始化工作,如显示一个进度条对话框等等
*/
@Override
protected void onPreExecute() {
super.onPreExecute();
}
/**
* 后台处理耗时任务,在子线程中进行,不可以进行UI操作
*
* @param strings 继承AsyncTask时的第一个泛型参数
* @return 将任务的执行结果返回
*/
@Override
protected Integer doInBackground(String... strings) {
return 0;
}
/**
* 当在后台任务中调用了publicProgress方法后,会得到调用
* 在此方法中可以进行UI操作
*
* @param values 后台任务传递的参数
*/
@Override
protected void onProgressUpdate(Integer... values){
}
/**
* 当任务执行完毕并通过return返回时,会得到调用
* 不在子线程中,可以进行UI操作
*
* @param integer return返回的数据
*/
@Override
protected void onPostExecute(Integer integer) {
}
}
复制代码
2 服务(主要讨论与活动的交流)
服务也属于四大组件之中的一种,所以创建一个服务时也要在清单文件中注册才能够进行使用
2.1 开启服务
-
startService:开启服务,服务开启后就与活动无关了,会在后台一直运行,除非手动调用了stopService()才能停止服务
-
bindService:绑定服务,通过绑定服务可以将活动与服务联系起来,并进行通信,通过Binder和ServiceConnection实现;
2.2 实现服务与活动的交流
- 首先在服务中创建一个继承Binder的类实例,并在这个类中定义想要跟活动进行交流 的方法,并通过服务重写的onBind()方法返回这个binder实例给活动
private DownloadBinder mBinder = new DownloadBinder();
/**
* 通过Binder实现服务与活动的信息交流
*/
public class DownloadBinder extends Binder{
//想要和服务进行交流的方法
public void startDownload() {
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
//把创建的binder传到活动,使得活动可以调用
return mBinder;
}
复制代码
- 在要进行交流的活动中创建一个ServiceConnection对象,并重写onServiceConnecte d()方法(当服务与活动成功进行绑定后调用),然后在此方法中通过服务传过来的IBi nder对象向下转型得到我们想要的binder对象
/**
* 服务与互动进行交流的工具
*/
private MyDownloadService.DownloadBinder downloadBinder;
private MyServiceConnection myServiceConnection = new MyServiceConnection();
/**
* 用做服务与活动进行交流的桥梁
*/
class MyServiceConnection implements ServiceConnection {
/**
* 当服务与活动成功进行绑定时调用
*
* @param service 所绑定的服务对应的Binder
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//获得Binder对象,便可以进行与服务的交流
downloadBinder = (MyDownloadService.DownloadBinder) service;
}
/**
* 当服务与活动断开连接时调用
*/
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
复制代码
- bindService()时需要把ServiceConnection对象也传入进去
//绑定服务,参数三:当绑定成功后自动创建服务的标志
bindService(intent, myServiceConnection, BIND_AUTO_CREATE);
复制代码
- 通过binder对象便可以调用服务中写好的方法,从而实现服务与活动的交流
downloadBinder.startDownload();
复制代码