您的位置:首页 > 移动开发 > Android开发

Android开发高级进阶(二)—多线程(实现简单下载器)

2016-09-07 18:06 507 查看

AsyncTask

AsyncTask适用于简单的异步处理,不需要借助线程和Handler即可实现。

AsyncTask

使用AsyncTask的步骤:

创建AsyncTask的子类,并为三个泛型参数指定类型。如果某个泛型参数不需要指定类型,则可将它指定为void。

根据需要实现以下方法:

doInBackground(Params…):后台线程将要完成的任务。该方法可以调用

publishProgress(Progress… values)方法更新任务的执行进度。

onProgressUpdate(Progress… values):在doInBackground()方法中调用publishProgress()方法更新任务的执行进度后,将会触发该方法。

onPreExecute():该方法将在执行后台耗时操作前被调用。通常用于完成一些初始化准备工作。

onPostExecute(Result result):当doInBackground()完成后,系统会自动调用onPostExecute()方法,并将doInBackground()方法的返回值传给该方法。

调用AsyncTask子类的实例的execute(Params… params)开始执行耗时任务。

这里通过实现一个简单的下载器来学习AsyncTask。

这个下载器就一个界面,包含一个输入框,用来输入下载地址,一个按钮,用来开始下载。

界面代码如下:activity_download.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
tools:context="com.trampcr.downloaddemo.MainActivity">

<EditText
android:id="@+id/et_url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:hint="请输入下载地址" />

<Button
android:id="@+id/btn_start_download"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/et_url"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:background="@drawable/button_style"
android:text="开始下载"
android:textColor="#000000" />

</RelativeLayout>


里是自定义按钮的形状。代码如下:button_style.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:topLeftRadius="10dp"
android:radius="8dp"
android:topRightRadius="10dp"
android:bottomLeftRadius="10dp"
android:bottomRightRadius="10dp" />
<stroke android:color="#000000"
android:width="0.7dp"/>
</shape>


根据上面的步骤,第一步是实现AsyncTask的子类,代码如下:DownloadAsyncTask.java

public class DownloadAsyncTask extends AsyncTask<URL, Integer, String> {

private ProgressDialog progressDialog;
private int hasRead = 0;
private Context context;

public DownloadAsyncTask(Context context) {
this.context = context;
}

@Override
protected String doInBackground(URL... params) {
try {
URLConnection urlConnection = params[0].openConnection();
InputStream inputStream= urlConnection.getInputStream();
String downloadFolderName = Environment.getExternalStorageDirectory() + File.separator + "trampcr" + File.separator;
File file = new File(downloadFolderName);
if (!file.exists()){
file.mkdir();
}
String fileName = downloadFolderName + "zxm.apk";
File apkFile = new File(fileName);
if (apkFile.exists()) {
apkFile.delete();
}
byte[] buff = new byte[1024];
int length = 0;
OutputStream outputStream = new FileOutputStream(fileName);
while ((length = inputStream.read(buff)) != -1) {
outputStream.write(buff, 0, length);
hasRead++;
publishProgress(hasRead);
}
outputStream.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
progressDialog.dismiss();
Toast.makeText(context, "下载完成", Toast.LENGTH_LONG).show();
}

@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(context);
//设置对话框标题
progressDialog.setTitle("任务正在进行中");
//设置对话框显示的内容
progressDialog.setMessage("正在下载,请稍等...");
//设置对话框的取消按钮
progressDialog.setCancelable(true);
//设置进度条的最大值
progressDialog.setMax(2000);
//设置进度条风格
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
//设置对话框的进度条是否显示进度
progressDialog.setIndeterminate(false);
progressDialog.show();
}

@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
//更新进度
progressDialog.setProgress(values[0]);
}
}


这里在onPreExecute()方法中实现了初始化并显示进度对话框,在doBackground()方法通过读文件、写文件完成下载任务,并调用publishProgress()方法发出更新进度,在onProgressUpdate()方法中执行更新进度,在onPostExecute()方法中销毁进度条对话框,并弹出Toast提示下载完成。

DownloadActivity.java

public class DownloadActivity extends AppCompatActivity implements View.OnClickListener{

//    public static final String DOWNLOAD_URL = "http://psoft.33lc.com:801/small/rootexplorer_33lc.apk";
private Button mBtnStartDownload;
private EditText mEtUrl;
private String mUrl;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_download);

mEtUrl = (EditText) findViewById(R.id.et_url);
mBtnStartDownload = (Button) findViewById(R.id.btn_start_download);

mBtnStartDownload.setOnClickListener(this);
}

@Override
public void onClick(View v) {
mUrl = mEtUrl.getText().toString().trim();
DownloadAsyncTask downloadAsyncTask = new DownloadAsyncTask(DownloadActivity.this);
try {
//            downloadAsyncTask.execute(new URL(DOWNLOAD_URL));
downloadAsyncTask.execute(new URL(mUrl));
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}


上一步实现了AsyncTask的子类,这一步就需要创建该子类的实例,并执行execute()开始执行任务。

所需要的权限:

<uses-permission android:name="android.permission.INTERNET"/>


效果图如下:



文/trampcr(简书作者)

原文链接:http://www.jianshu.com/p/6a558a23084a

著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 多线程
相关文章推荐