异步任务:
安卓的单线程模型
耗时的任务放在其他线程
AsyncTask
在子线程中更新UI
封装、简化异步操作
目的:
图片转化成流:基本的网络操作
上面是慕课网的AsyncTask的讲解(https://www.imooc.com/learn/377),老师把继承了AsyncTask的子类写做内部类,下面我来展示一下独立类的写法
AsyncTask作为独立类
我要感谢这篇博客https://blog.csdn.net/shadow066/article/details/17380399,它用了接口的回调实现
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.lenovo.androidasynctask.MainActivity">
<ImageView
android:layout_weight="100"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/image"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/button"
android:text="下载图片"
/>
</LinearLayout>
然后是一个接口,这个很重要
TaskListener.java
package com.example.lenovo.androidasynctask;
import android.graphics.Bitmap;
/**
* Created by lenovo on 2018/3/22.
*/
public interface TaskListener {
public void onCompletedListener(Bitmap result);
}
MainActivity.java
在按钮点击事件中new一个Mytask类,加上构造参数并执行我们图片的目标地址。
然后在里面实现一下接口的抽象方法onCompletedListener()方法,这个方法的参数就是下载的图片以bitmap形式存储的。然后在方法里给ImageView填充图片。
package com.example.lenovo.androidasynctask;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
public class MainActivity extends Activity {
private ProgressDialog dia;
String picture = "http://b.hiphotos.baidu.com/image/pic/item/908fa0ec08fa513d17b6a2ea386d55fbb2fbd9e2.jpg";
private Button button;
private ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=(Button)findViewById(R.id.button);
imageView=(ImageView)findViewById(R.id.image);
dia=new ProgressDialog(this);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
imageView.setImageBitmap(null);
new Mytask(dia,MainActivity.this,new TaskListener(){
@Override
public void onCompletedListener(Bitmap result) {
imageView.setImageBitmap(result);
}
}).execute(picture);
}
});
}
}
最后是继承了AsyncTask的独立类Mytask
这个类的构造方法有三个参数(ProgressDialog,Context,TaskListener),第三个参数就是我们可爱的接口
当任务执行完后,在onPostExecute()方法中调用TaskListener接口中的onCompletedListenr()方法,放心我们会在MainActivity的点击事件实现这个方法的。
package com.example.lenovo.androidasynctask;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.content.Context;
import android.os.AsyncTask;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageView;
import android.widget.ProgressBar;
import com.example.*;
/**
* Created by lenovo on 2018/3/22.
*/
public class Mytask extends AsyncTask<String ,Integer,Bitmap> {
private Context context;
private TaskListener taskListener;
private ProgressDialog dia;
//MyTask的构造方法
public Mytask(ProgressDialog dias,Context context, TaskListener listener) {
super();
dia=dias;
this.context = context;
this.taskListener = listener;
}
//在doInBackground()方法执行前调用,主要执行一些初始化的工作,在UI线程中执行
@Override
protected void onPreExecute() {
super.onPreExecute();
dia.setTitle("提示信息");
dia.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dia.setCancelable(false);
dia.show();
}
//干活的代码写在这里
@Override
protected Bitmap doInBackground(String... strings) {
Bitmap bitmap=null;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
InputStream inputStream=null;
try{
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(strings[0]);
HttpResponse httpResponse = httpClient.execute(httpGet);
if(httpResponse.getStatusLine().getStatusCode()==200){
inputStream = httpResponse.getEntity().getContent();
//先获得文件的总长度
long file_length = httpResponse.getEntity().getContentLength();
int len=0;
byte [] data =new byte[1024];
int total_length=0;
int value=0;
while((len = inputStream.read(data))!=-1){
total_length+=len;
value=(int)((total_length/(float)file_length)*100);
//调用updata函数,跟新进度
publishProgress(value);
outputStream.write(data,0,len);
}
byte[] result =outputStream.toByteArray();
bitmap= BitmapFactory.decodeByteArray(result,0,result.length);
}
}
catch (Exception e){
e.printStackTrace();
}finally {
if(inputStream!=null){
try{
inputStream.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
return bitmap;
}
//更新进度条
//在任务执行过程中调用publishProgress()方法报告进度,此方法被调用,并在UI县城中执行
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
dia.setProgress(values[0]);
}
//在工作完成后次方法被调用,在UI线程中执行
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
dia.dismiss();
taskListener.onCompletedListener(result);
}
@Override
protected void onCancelled(Bitmap result) {
super.onCancelled(result);
}
}
这期间还遇到了几个小插曲
上图总的doInbackground()方法中那些http的类,我也不知道用的哪个jar包,总之在上图右边的libs我把要用的都加上了,有想要的在评论里留下邮箱哦。
然后这么多jar包在一块就变异出错了,出错的话看这俩博客
1.解决了jar包里重复文件的问题
https://www.cnblogs.com/skyeblogs/p/8514187.html
2.解决了
Error:Execution failed for task ':app:transformResourcesWithMergeJavaResForDebug'.
> More than one file was found with OS independent path 'META-INFXXX'