Thread和AsyncTask使用:
来源:互联网 发布:linux查看光纤卡流量 编辑:程序博客网 时间:2024/05/31 13:16
1.Thread使用:
继承Thread类:
public class MyThread extends Thread { @Override public void run() { //线程中处理的逻辑 }}
调用:
new MyThread().start();
实现Runnable:
public class MyThread implements Runnable { @Override public void run() { //线程中处理的逻辑 }}
调用:
MyThread myThread=new MyThread() new Thread(myThread).start();
异步消息处理
public class ThreadTestActivity extends Activity { private TextView text; private Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case 0: //子线程不允许操作UI.,在这里操作UI 防止线程堵塞 text.setText("这里操作UI,防止线程堵塞"); break; case 1: break; default: break; } } }; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button=findViewById(R.id.start_download); text=(TextView)findViewById(R.id.text_view); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { new Thread(new Runnable() { @Override public void run() { Message message=new Message(); message.what=0; handler.sendMessage(message); } }).start(); } }); }}
1.Message存储少量数据,用于进程间交换数据。除了what字段,还有arg1 arg2 以及obj.
2.Handler处理Message发送过来的信息,发送消息一般是Handler的sedMessage()方法。最终会传递到Handler的Handler的handleMessage()方法中。
3.MessageQueue是存放Handler的sendMessage()发送过来的消息,这些消息存在一个队列中,等待被处理。每个线程中只有一个MessageQueue对象。
4.Loop:MessageQueue的管家,调用Loop的loop()方法后,就会无线循环。没发现MessageQueue中存在消息队列,就会从中取出,传递到Handler的handleMessage()中。每个线程中只有已给Loop对象
runOnUiThread()方法就是这个原理实现的
2.AsyncTask使用:
继承AsyncTask,实现一个抽象方法 doInBackground()
public class MyAsyncTask extends AsyncTask<String,Integer,Integer> { @Override protected Integer doInBackground(String... strings) { return null; }}
Params:执行AsyncTask时需要传入的参数,可用于在后台任务
Progress:界面上显示当前进度,只用这里指定泛型作为进度单位
Result:当任务执行完,需要对结果进行返回,可以指定泛型作为返回值类型
一些常用方法:
onPreExecute()
这个会在执行后台任务之前被调用,常用语一些初始化操作
doInBackground(Params…)
这个方法的代码都会在子线程中执行,常用的耗时操作都在这里执行,可以通过reture返回执行结果。AsyncTask的第三个参数指定为Void,则可以不返回任务执行结果。如果需要操作UI,比如反馈当前任务进度。可以调用publishProgress(Progress…)
onProgressUpdata(Progress..)
调用 publishProgress()方法后,onProgressUpdata()方法会很快被调用,这个方法携带过来的参数就是在后台任务传递过来的,可以利用参数中的数值进行UI操作
onPostExecute(Result…)
后台执行完毕通过return返回结果时,就会调用此方法,doInBackground()返回的结果会作为参数传递到此方法中,比如提醒任务执行结果
例子:DownloadTask.java代码
public class DownloadTask extends AsyncTask<String, Integer, Integer> { public static final int TYPE_SUCCESS = 0; public static final int TYPE_FAILED = 1; public static final int TYPE_PAUSED = 2; public static final int TYPE_CANCELED = 3; private DownloadListener listener; private boolean isCanceled = false; private boolean isPaused = false; private int lastProgress; public DownloadTask(DownloadListener listener) { this.listener = listener; } @Override protected Integer doInBackground(String... params) { InputStream is = null; RandomAccessFile savedFile = null; File file = null; try { long downloadedLength = 0; // 记录已下载的文件长度 String downloadUrl = params[0]; String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/")); String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath(); file = new File(directory + fileName); if (file.exists()) { downloadedLength = file.length(); } long contentLength = getContentLength(downloadUrl); Log.d("TAG", "contentLength: "+contentLength); if (contentLength == 0) { return TYPE_FAILED; } else if (contentLength == downloadedLength) { // 已下载字节和文件总字节相等,说明已经下载完成了 return TYPE_SUCCESS; } OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() // 断点下载,指定从哪个字节开始下载 .addHeader("RANGE", "bytes=" + downloadedLength + "-") .url(downloadUrl) .build(); Response response = client.newCall(request).execute(); if (response != null) { is = response.body().byteStream(); savedFile = new RandomAccessFile(file, "rw"); savedFile.seek(downloadedLength); // 跳过已下载的字节 byte[] b = new byte[1024]; int total = 0; int len; while ((len = is.read(b)) != -1) { if (isCanceled) { return TYPE_CANCELED; } else if(isPaused) { return TYPE_PAUSED; } else { total += len; savedFile.write(b, 0, len); // 计算已下载的百分比 int progress = (int) ((total + downloadedLength) * 100 / contentLength); publishProgress(progress); } } response.body().close(); return TYPE_SUCCESS; } } catch (Exception e) { e.printStackTrace(); } finally { try { if (is != null) { is.close(); } if (savedFile != null) { savedFile.close(); } if (isCanceled && file != null) { file.delete(); } } catch (Exception e) { e.printStackTrace(); } } return TYPE_FAILED; } @Override protected void onProgressUpdate(Integer... values) { int progress = values[0]; //更新下载进度 if (progress > lastProgress) { listener.onProgress(progress); lastProgress = progress; } } @Override protected void onPostExecute(Integer status) { switch (status) { case TYPE_SUCCESS: listener.onSuccess(); break; case TYPE_FAILED: listener.onFailed(); break; case TYPE_PAUSED: listener.onPaused(); break; case TYPE_CANCELED: listener.onCanceled(); default: break; } } public void pauseDownload() { isPaused = true; } public void cancelDownload() { isCanceled = true; } /** * 获取文件总字节数 * @param downloadUrl * @return contentLength * @throws IOException */ private long getContentLength(String downloadUrl) throws IOException { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url(downloadUrl) .build(); Response response = client.newCall(request).execute(); if (response != null && response.isSuccessful()) { long contentLength = response.body().contentLength(); response.close(); return contentLength; } return 0; }}
DownloadListener.java代码
public interface DownloadListener { void onProgress(int progress); void onPaused(); void onCanceled(); void onSuccess(); void onFailed();}
DownloadService.java代码
public class DownloadService extends Service { private String downloadUrl; private DownloadTask downloadTask; private DownloadListener downloadListener=new DownloadListener() { @Override public void onProgress(int progress) { getNotificationManage().notify(1,getNotification("download...",progress)); } @Override public void onPaused() { downloadTask=null; Toast.makeText(DownloadService.this,"Paused Download",Toast.LENGTH_LONG).show(); } @Override public void onCanceled() { downloadTask=null; stopForeground(true); Toast.makeText(DownloadService.this,"Canceled Download",Toast.LENGTH_LONG).show(); } @Override public void onSuccess() { downloadTask=null; //前台服务关闭,并创建一个下载成功通知 stopForeground(true); getNotificationManage().notify(1,getNotification("下载完成",-1)); Toast.makeText(DownloadService.this,"Download success",Toast.LENGTH_LONG).show(); } @Override public void onFailed() { downloadTask=null; //下载失败关闭前台服务通知,并创建一个下载失败通知 stopForeground(true); getNotificationManage().notify(1,getNotification("Download Failed",-1)); Toast.makeText(DownloadService.this,"Download failed",Toast.LENGTH_LONG).show(); } }; private DownloadBind mBind=new DownloadBind(); class DownloadBind extends Binder{ public void startDownload(String url){ if (downloadTask==null){ DownloadTask downloadTask=new DownloadTask(downloadListener); downloadUrl=url; downloadTask.execute(downloadUrl); startForeground(1,getNotification("download...",0)); Toast.makeText(DownloadService.this,"download...",Toast.LENGTH_LONG).show(); } } public void pauseDownload(){ if (downloadTask!=null){ downloadTask.pauseDownload(); } } public void cancelDownload(){ if (downloadTask!=null){ downloadTask.cancelDownload(); }else { if (downloadUrl!=null){ //取消下载,删除文件,关闭通知 String fileName=downloadUrl.substring(downloadUrl.lastIndexOf("/")); String fileDir= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath(); File file=new File(fileDir+fileName); if (file.exists()){ file.delete(); } getNotificationManage().cancel(1); stopForeground(true); Toast.makeText(DownloadService.this,"Cancel download",Toast.LENGTH_LONG).show(); } } } } @Override public IBinder onBind(Intent intent) { return mBind; } public NotificationManager getNotificationManage(){ return (NotificationManager) getSystemService(NOTIFICATION_SERVICE); } private Notification getNotification(String title,int progress){ Intent intent=new Intent(this,MainActivity.class); PendingIntent pi=PendingIntent.getActivity(this,0,intent,0); NotificationCompat.Builder builder=new NotificationCompat.Builder(this); builder.setContentTitle(title).setSmallIcon(R.mipmap.ic_launcher).setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher)); builder.setContentIntent(pi); if (progress>0){ builder.setContentTitle(progress+"%"); builder.setProgress(100,progress,false); } return builder.build(); }}
DownloadService服务中实现DownloadListener中的5个方法,onProgress()方法中创建通知栏,在下拉状态栏中实时更新下载进度。onSuccess()方法中关闭前台任务,创建一个新通知告诉用户下载完成了。
DownloadBind中提供三个方法 分别分别用于启动,暂停,和取消下载任务。startDownload()方法中实例了DownloadTask,并调用了execute()方法开启下载。这个下载服务就作为已给前台服务运行了startForeground()方法在系统状态栏创建持续运行通知
MainActivity.java代码
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button startBtn, pauseBtn, cancelBtn; private DownloadService.DownloadBind downloadBind; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { downloadBind = (DownloadService.DownloadBind) iBinder; } @Override public void onServiceDisconnected(ComponentName componentName) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startBtn = (Button) findViewById(R.id.start_download); pauseBtn = (Button) findViewById(R.id.pause_download); cancelBtn = (Button) findViewById(R.id.cancel_download); startBtn.setOnClickListener(this); pauseBtn.setOnClickListener(this); cancelBtn.setOnClickListener(this); Intent intent = new Intent(MainActivity.this, DownloadService.class); startService(intent);//启动服务 bindService(intent, connection, BIND_AUTO_CREATE);//绑定bind if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); } } @Override public void onClick(View view) { if (downloadBind == null) { return; } switch (view.getId()) { case R.id.start_download: String url = "https://raw.githubusercontent.com/guolindev/eclipse/master/eclipse-inst-win64.exe"; String url2="http://sw.bos.baidu.com/sw-search-sp/software/71bdb07e88935/Firefox-55.0.2.6435-setup.exe"; downloadBind.startDownload(url2); break; case R.id.pause_download: downloadBind.pauseDownload(); break; case R.id.cancel_download: downloadBind.cancelDownload(); break; default: break; } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { case 1: if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "拒绝权限将无法使用程序", Toast.LENGTH_SHORT).show(); finish(); } break; default: } } @Override protected void onDestroy() { super.onDestroy(); unbindService(connection); }}
layout布局文件就不贴出来了,感觉已经写了很长了。
在onCreatView()中启动服务,和bindService()绑定service.
ServiceConnection 中实例了DownloadBind。有了DownloadBind的实例就可以调用其中的StartDownload(),pauseDownload(),cancelDownload()三个方法了。分别对应到不同按钮的点击事件中。
另外则是一个权限的动态申请了。
- Thread和AsyncTask使用:
- thread & asynctask 的使用
- Thread ,Service 和 AsyncTask
- AsyncTask(异步)和Thread(线程)的使用与对比
- 使用AsyncTask--->对Handler 和Thread 进行了封装
- AsyncTask(异步)和Thread(线程)的使用与对比
- AsyncTask(异步)和Thread(线程)的使用与对比
- AsyncTask(异步)和Thread(线程)的使用与对比
- 异步AsyncTask,怎样停止AsyncTask和Thread
- 怎样停止AsyncTask和Thread
- Android 停止AsyncTask和Thread
- AsyncTask和Thread Handler对比
- AsyncTask和Thread+Handler对比
- AsyncTask和Thread Handler对比
- AsyncTask与Thread+Handler的区别、AsyncTask的使用
- AsyncTask和Thread加Handler的区别
- android如何停止Thread和AsyncTask
- Android怎样停止AsyncTask和Thread
- 树莓派—qt安装及其环境搭建全攻略
- C#204课的主要内容
- Vue2 vue-cli 中stylus 报错unexpected indent
- ssm学习总结-Ajax实现简单的登录校验
- js和html5生成自动排列的对话框
- Thread和AsyncTask使用:
- 了解geohash编码,做了个小测试
- IT人生畅想
- CodeForces
- linux 简单监控命令
- SpringMVC中使用Interceptor拦截器
- DPDK在Atom和J1900平台上运行失败的解决方法
- IDEA导入多个项目jar包和符号不存在问题
- HDU 4609 3-idiots(FFT+组合计数)