AsyncTask下载网络文件,并显示下载进度
2015-08-10 17:32
716 查看
一些说明
ProgressBar.setProgress():刷新UI操作必须运行在UI线程中,但是setProgress()方法里面已经做了同步操作,所以可以在非UI线程中调用
webView.loadUrl():
耗时操作不能运行在UI线程中,但是loadUrl()方法进过特殊处理,所以可以在UI线程中调用
异步任务demo
> AsyncTask下载网络文件,并显示下载进度test_AsyncTask.java
package com.example.testasynctask; import java.io.File; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; public class test_AsyncTask extends Activity { private ProgressBar pb_down; private TextView tv_downProgress; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test_async_task); Button btn_down = (Button) findViewById(R.id.btn_down); btn_down.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String downloadUrl = "http://501xm.cache.cheerpic.com/source/chizi/201508/32283-20150804.apk"; String saveDir = Environment.getExternalStorageDirectory() .getAbsolutePath() + "/test/download"; Log.d("pointwall", saveDir); DownTask downTask = new DownTask(); downTask.execute(downloadUrl, saveDir); } }); } class DownTask extends AsyncTask<String, // Params,启动任务时传入的参数类型 Integer, // Progress,后台任务执行中返回值的类型 String// Result,后台任务执行完成返回结果的类型 > { /** * 执行后台耗时操作前被调用,通常完成一些初始化操作,运行在主线程 */ @Override protected void onPreExecute() { tv_downProgress = (TextView) findViewById(R.id.tv_downProgress); pb_down = (ProgressBar) findViewById(R.id.pb_down); pb_down.setMax(100); } /** * 必须重写,异步执行后台将要完成的任务,运行在子线程 */ @Override protected String doInBackground(String... params) { String downloadUrl = params[0]; String saveDir = params[1]; try { int currentProgress = 0;// 当前已下载文件长度 URL url = new URL(downloadUrl); HttpURLConnection conn = (HttpURLConnection) url .openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(8000); conn.setReadTimeout(8000); if (conn.getResponseCode() == 200) { int length = conn.getContentLength(); InputStream is = conn.getInputStream(); byte[] b = new byte[1024]; int len; File file2 = new File(saveDir); if (!file2.exists()) { file2.mkdirs(); } File file = new File(saveDir, getFileName(downloadUrl)); RandomAccessFile raf = new RandomAccessFile(file, "rwd"); while ((len = is.read(b)) != -1) { raf.write(b, 0, len); currentProgress += len; // TODO 下载len个长度的字节 int downRate = (int) ((long) currentProgress * 100 / length); publishProgress(downRate); } raf.close(); } } catch (Exception e) { e.printStackTrace(); } return saveDir + getFileName(downloadUrl); } /** * 在doInBackgroung()方法中调用publishProgress()方法 更新任务的执行进度后,就会触发该方法,运行在主线程 */ @Override protected void onProgressUpdate(Integer... values) { int downRate = values[0]; Log.d("ziru", downRate + ""); pb_down.setProgress(downRate); tv_downProgress.setText("下载了:" + downRate + "%"); } /** * 当doInBackground()完成后,系统会自动调用,运行在主线程 */ @Override protected void onPostExecute(String result) { tv_downProgress.setText("下载完成"); } /** * 根据下载地址获取app名字 * @param downloadDir 下载地址 * @return app名字,如:32283-20150804.apk */ private String getFileName(String downloadDir) { int index = downloadDir.lastIndexOf("/"); return downloadDir.substring(index + 1); } } }
test_asynctask.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="vertical" android:padding="5dp" > <ProgressBar android:id="@+id/pb_down" style="@android:style/Widget.ProgressBar.Horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" /> <TextView android:id="@+id/tv_downProgress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="等待下载" android:textSize="20sp" /> <Button android:id="@+id/btn_down" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="下载" /> </LinearLayout>
权限
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
AsyncTask注意事项
必须在UI线程中创建AsyncTask实例必须在UI线程中调用AsyncTask.execute()方法
重写的四个方法onPreExecute(), doInBackground(), onProgressUpdate(), onPostExecute()是系统调用的,不应手动调用
每个AsyncTask只能被执行一次,多次调用会引发异常
只有doInBackground()运行在其他线程,onPreExecute(), onProgressUpdate(), onPostExecute()三个方法都运行在UI线程
如何取消AsyncTask
1. 在Activity的onPause()方法中將AsyncTask标记为cancel状态@Override protected void onPause(){ super.onPause(); if(mAsyncTask != null && mAsyncTask.getStatus() == AsyncTask.Status.RUNNING){ // cancel方法只是將对应的AsyncTask标记为cancel状态,并不是真正的取消线程的执行 mAsyncTask.cancel(true); } }
2. 在doInBackground()和onProgressUpdate()方法里做取消异步任务处理
@Override protected String doInBackground(String... params) { if(isCancelled()){ break; } return null; } @Override protected void onProgressUpdate(Integer... values) { if(isCancelled()){ break; } }
相关文章推荐
- TCP/IP协议三次握手与四次握手流程解析
- 机器学习之从logistic到神经网络算法
- Burpsuite截获https数据包
- java.io.IOException: Server returned HTTP response code: 500 for URL解决办法
- APP HTTP接口报文的加密与压缩
- (转载)卷积神经网络
- [Android基础]Android中使用HttpURLConnection
- Http协议与TCP协议理解
- HTTP调试工具推荐:Fiddler
- 《计算机网络》-----课本内容
- TCP/IP数据报格式分析
- nginx安全下载模块ngx_http_secure_link_module
- 黑马程序员-网络编程(一)
- Android 网络通信框架Volley简介(Google IO 2013)
- Java基础——网络编程(一)
- 卷积神经网络
- qperf测量网络带宽和延迟
- Http Session和Cookie
- 基于Java的socket网络通信
- 谈谈如何训练一个性能不错的深度神经网络