使用一个开新工作线程处理一些耗时任务后,如何通知到启动它的Activity?
这篇文章主要用的是Android为我们提供的一种封装好的工具——"ResultReceiver"
【IntentService和ResultReceiver】
IntentService继承自service,在IntentService中我们开启一个线程执行下载任务(service和你的app其实是在一个线程中,因此不想阻塞主线程的话必须开启新的线程。
//在这里根据url进行下载文件,并通过receiver把需要更新的progressbar的值放在bundle传过去
public class DownloadService extends IntentService {
public static final int UPDATE_PROGRESS = 8344;
public DownloadService() {
super("DownloadService");
}
@Override
protected void onHandleIntent(Intent intent) {
String urlToDownload = intent.getStringExtra("url");
ResultReceiver receiver = (ResultReceiver) intent.getParcelableExtra("receiver");
HttpURLConnection connection ;
try {
URL url = new URL(urlToDownload);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
// this will be useful so that you can show a typical 0-100% progress bar
int fileLength = connection.getContentLength();
Log.d("test","fileLength:"+fileLength);
// download the file
InputStream input = connection.getInputStream();
OutputStream output = new FileOutputStream("/sdcard/new.apk");
byte data[] = new byte[2048];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
Bundle resultData = new Bundle();
resultData.putInt("progress" ,(int) (total * 100 / fileLength));
receiver.send(UPDATE_PROGRESS, resultData);
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//记得注册
activity中这样调用DownloadService
progressDialog.show();
Intent intent = new Intent(this, DownloadService.class);
intent.putExtra("url",url);
intent.putExtra("receiver", new DownloadReceiver(new Handler()));
startService(intent);
activity中定义一个广播接收器继承ResultReceiver,ResultReceiver允许我们接收来自service中发出的广播
//使用ResultReceiver接收来自DownloadService的下载进度通知
private class DownloadReceiver extends ResultReceiver {
public DownloadReceiver(Handler handler) {
super(handler);
}
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
if (resultCode == DownloadService.UPDATE_PROGRESS) {
int progress = resultData.getInt("progress");
//(true)就是根据你的进度可以设置现在的进度值。
//(false)就是滚动条的当前值自动在最小到最大值之间来回移动,形成这样一个动画效果
progressDialog.setIndeterminate(false);
progressDialog.setProgress(progress);
if (progress == 100) {
progressDialog.dismiss();
//自动安装下载的apk
File file=new File("/sdcard/new.apk");
Intent installIntent = new Intent(Intent.ACTION_VIEW);
installIntent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(installIntent);
}
}
}
}
说明:
1.IntentService是Service类的子类,用来处理异步请求。客户端可以通过startService(Intent)方法传递请求给IntentService,IntentService通过worker thread处理每个Intent对象,执行完所有的工作之后自动停止Service。说明:worker thread处理所有通过传递过来的请求,创建一个worker queue,一次只传递一个intent到onHandleIntent中,从而不必担心多线程带来的问题。处理完毕之后自动调用stopSelf()方 法;默认实现了Onbind()方法,返回值为null;
使用IntentService需要两个步骤:
1、写构造函数
2、复写onHandleIntent()方法
2.activity调用service时,传递的广播接收器需要传入一个Handler,并且这个Handler是可以为null的。这个Handler的作用只有一个,就是控制回调函数执行在创建Handler的线程。如果在Activity主线程创建的handler实例,则回调也会在主线程执行。就可以直接在回调中操作UI。也就是在onReceiveResult更新UI。
3.在intentservice中最主要的方法是通过 receiver.send方法就参数传递给activity。源码就是在调用send方法的线程中执行onReceiveResult回调。
亲,给个赞鼓励一下吧~