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

异步处理任务工具类(AsyncTask)实现多张图片的下载(已知url)

2016-09-17 19:14 579 查看
异步加载任务机制是为了处理多个对象同时对主线程操作而出现的,作用和handler是相似的,在后台进行操作之后,可以更改UI。但他的实现方式比handler容易许多。
AsycTask中通过四个方法实现功能:onPreExecute();在执行具体操作之前执行,可以进行一些操作的初始化;onPostExecute();更新操作完成之后执行;doInBackground;具体的逻辑操作,不会修改UI,将更改操作传送给onProgressUpdate;onProgressUpdate();负责执行更新UI的操作;除了doInbackground是子线程,其他的都是主线程。
本例涉及知识点:I/O流,异步处理任务,动态加载控件;所用文件为数据截取软件截取出来的相关的图片url和名字文件。
一,使用表格布局进行展示,将图片和文字进行封装到一个布局中,在代码中动态加载;
二,使用scrollView包裹表格布局,实现内容的滑动;
三,使用asynctask实现图片的批量加载到布局中;


<?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"
>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">//使scrollview里面的元素填满布局,使用fill-parent没用
<GridLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/gridlayout"
android:columnCount="3">

</GridLayout>
</ScrollView>
</RelativeLayout>


其中,scrollview中的fillviewport属性为使布局填满屏幕,在此处使用fill-parent没用;
首先,布局的初始化:


public class Main6Activity extends AppCompatActivity {
GridLayout gridLayout;//表格布局,加载relativelayout
RelativeLayout[]relativeLayouts;//动态加载relativelayout的数组
TextView[]textViews;//存放textview
ImageView[]imageViews;//存放imageview
int width,height;
List<String>carName;//存放截取出来的车的名字
List<String>carLogo;//存放截取出来的车的URL

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

carName = new ArrayList<>();
carLogo = new ArrayList<>();
gridLayout = (GridLayout) findViewById(R.id.gridlayout);


第一步:流操作实现图片URL和名字的获取


private void readInfo(){
InputStream inputStream=null;
try {
inputStream = getResources().getAssets().open("car.txt");
StringBuilder builder = new StringBuilder();
Reader reader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(reader);
String temp=null;
while((temp=bufferedReader.readLine())!=null){
builder.append(temp);
}
String carInfo=builder.toString();
String[] carsInfo = carInfo.split("###");
for(String car:carsInfo){
String [] cars=car.split("#");
carName.add(cars[0]);
carLogo.add(cars[1]);
}
int n=carLogo.size();
relativeLayouts = new RelativeLayout
;
textViews = new TextView
;
imageViews = new ImageView
;
} catch (IOException e) {
e.printStackTrace();
}
}


relativelayout和textview以及imageview是动态的加载,所以使用数组来表现;大小为截取之后的carname的大小;
第二步,初始化布局,以及动态加载布局;


private void initView(){
for(int n=0;n<relativeLayouts.length;n++){
RelativeLayout relativeLayout = new RelativeLayout(this);

ImageView imageView = new ImageView(this);
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
imageView.setImageResource(R.mipmap.ic_launcher);

TextView textView = new TextView(this);
textView.setText(carName.get(n));
textView.setTextColor(Color.parseColor("#2c2c2c"));
textView.setTextSize(20);
textView.setBackgroundColor(Color.parseColor("#ffffff"));

relativeLayouts
=relativeLayout;
imageViews
= imageView;
textViews
= textView;

relativeLayout.addView(textView,width,height);
relativeLayout.addView(imageView,width,height/3);
gridLayout.addView(relativeLayout);
}

}


使用add方法将布局加载到布局之中。

第三步。异步处理任务工具类处理图片下载:

图片URL保存在list集合carLogo中,将集合作为参数传入进行逻辑操作;参数为string类型,在oncreate方法中,将集合转换为数组,然后传入asynctask

String []carlogo = new String[carLogo.size()];
carlogo = carLogo.toArray(carlogo);
new downLoadImage().execute();


doInBackground方法中网络下载图片,

URL url = new URL(params[i]);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

int len=0;
byte[] bytes = new byte[1024];
while((len=inputStream.read(bytes))!=-1){
byteArrayOutputStream.write(bytes,0,len);
}


然后转换为图片对象;

byte[] image = byteArrayOutputStream.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(image, 0, image.length);


重点内容

问题一:此时如果直接将bitmap对象穿过去,会发生意想不到的效果,会发生图片和名字不对应的情况。原因是:doInBackground是子线程,而更改UI是主线程,发生了线程抢占资源的情况,而加锁不太好,具体原因不是很明白;所以给的解决方法是用一个map集合来维护。根据map集合的键值相对性。

HashMap<Integer, Bitmap> hashMap = new HashMap<>();
hashMap.put(i, bitmap);
publishProgress(hashMap);


publishProgress是将逻辑操作的结果发送到主线程进行UI的修改;

onProgressUpdate负责修改UI;

根据键取出相应的值,然后imageview负责修改;

protected void onProgressUpdate(HashMap<Integer, Bitmap>... values) {

Set<Integer> keys = values[0].keySet();
Iterator<Integer>it=keys.iterator();
while(it.hasNext()){
int position=it.next();
Bitmap bitmap = values[0].get(position);
imageViews[position].setImageBitmap(bitmap);
}
}


运行结果如下:



demo附上,有意愿的可以探讨一下~;

异常处理任务工具类之多图片下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  asynctask Android