实验五 多线程
1、 实验目的
(1) 验证多线程下同步UI的实现方式
2、实验要求
(1) 认真填写实验报告,要求附加部分运行界面和主要代码;
(2) 对设计好的程序,检查输出是否符合预期,如有错请分析错误原因并解决;
3、实验内容
(1) 在子线程中进行模拟下载,下载过程中发送通知消息;
(2) 在主线程的Handler中处理消息,更新界面;
https://www.jianshu.com/p/1067380e05c3
(3) 采用AsyncTask派生类实现多线程异步下载;
https://www.jianshu.com/p/e7ff6b8b10d9
(4) 实现多线程图片下载程序;
效果图:
1
2
代码:
package com.example.externalfile;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class MainActivity extends AppCompatActivity {
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
//检查是否有写入外部文件的权限
if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},0);
}
/* 写入字符串到文件的操作
//得到外部公开文件夹下面的DOWNLOADS文件夹路劲
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
// 在该文件夹下创建新的文件
File file = new File(path, "1.txt" );
// 打开一个文件输出流 捕获异常
try {
// 文件流 只能二进制
FileOutputStream fileOutputStream = new FileOutputStream(file);
// 封装一个字符串的流
OutputStreamWriter writer = new OutputStreamWriter(fileOutputStream);
// 等于-1 就读完了
writer.close();
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
*/
}
//请求结果的回调
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == 0){
// 对应String[]的第一个
if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
}else{
// 不允许就继续。。。
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},0);
}
}
}
// 下载按钮的功能
public void download(View v){
// 准备一个URL
try {
URL url1 = new URL("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556464174901&di=822acd616133de9bffdd846a73d890aa&imgtype=jpg&src=http%3A%2F%2Fyesky2.img.xzstatic.com%2Fnews%2F201901%2F112257-5c341791b5136.jpg");
URL url2 = new URL("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556464174901&di=822acd616133de9bffdd846a73d890aa&imgtype=jpg&src=http%3A%2F%2Fyesky2.img.xzstatic.com%2Fnews%2F201901%2F112257-5c341791b5136.jpg");
new MyAsyncTask().execute(url1,url2);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
// 网上下载图片的异步任务
// 希望传个url给他就可以了 下载过程中传个整数表示进度
class MyAsyncTask extends AsyncTask<URL,Integer,Integer>{
@Override
// 点点点表示很多URL
protected Integer doInBackground(URL... urls) {
for(int i=0;i<urls.length;i++){
// 定义统一资源定位符URL
URL url = urls[i];
// 打开一个链接
try {
URLConnection connection = url.openConnection();
// 确定访问的文件有多大
int size = connection.getContentLength();
// 读一个文件 打开输入流
InputStream inputStream = connection.getInputStream();
// 开100个字节的缓冲区 实际很大的
byte[] bytes = new byte[100];
int len = -1;
int totalen = 0;//用来计算百分比的
// 打开文件
//得到外部公开文件夹下面的DOWNLOADS文件夹路劲
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
// 在该文件夹下创建新的文件
File file = new File(path, ""+i+".jpg");
// 打开一个文件输出流 捕获异常
try {
// 文件流 只能二进制
FileOutputStream fileOutputStream = new FileOutputStream(file);
// 等于-1 就读完了
while ((len = inputStream.read(bytes))!= -1){
// 写到文件里面 二进制流
fileOutputStream.write(bytes,0,len);
// 一共读了多少 用来算出百分比
totalen = totalen + len;
// 读的过程中更新界面
publishProgress(i,size,totalen);
// 加一个线程的sleep不然下载太快,反应不过来
Thread.sleep(1);
}
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
textView.setText("Finished!");
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
textView.setText("File:"+values[0]+"size:"+values[1]+" Percent:"+Float.valueOf(values[2])/values[1]);
}
}
}
重要细节
文件写入权限
访问网络权限
fileOutputStream说明
写入字符串-1
写入字符串-2
自动整理代码