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

本文介绍了如何利用AsyncTask在Android中实现多张图片的异步下载。通过将图片URL保存在列表中,传入异步任务处理。在doInBackground方法中下载图片并转换为Bitmap。为了避免图片与名字不对应的问题,使用Map集合保持键值对应。publishProgress和onProgressUpdate分别用于更新进度和在主线程修改UI。附带了运行结果和代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

异步加载任务机制是为了处理多个对象同时对主线程操作而出现的,作用和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[n];
            textViews = new TextView[n];
            imageViews = new ImageView[n];
        } 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[n]=relativeLayout;
            imageViews[n] = imageView;
            textViews[n] = 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附上,有意愿的可以探讨一下~;
异常处理任务工具类之多图片下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值