线程间通信-使用EventHandler下载网络图片

Posted 茹茹

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程间通信-使用EventHandler下载网络图片相关的知识,希望对你有一定的参考价值。

作者:韩茹

公司:程序咖(北京)科技有限公司

程序咖:IT职业技能评测平台

网址:https://www.chengxuka.com

前面我们已经搞明白了鸿蒙应用开发过程中的线程之间是如何通信的。就是利用EventHandler,InnerEvent,EventRunner等。

我们想实现的内容是,点击按钮进行下载网络上的图片,图片显示前先显示进度条。当图片下载完毕后,进度条消失,显示图片。

先来看一下效果:

<img src="https://img.chengxuka.com/downloadimageyunxing1.gif" style="zoom:50%;" />

因为是在EventHandler这个Demo上随手写的,我没有重新创建工程。

一、XML布局

在layout目录下新建xml布局文件,demo4_eventhandler_image.xml,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:
    ohos:
    ohos:padding="20vp"

    ohos:orientation="vertical">

    <Button
        ohos:id="$+id:btn1"
        ohos:
        ohos:
        ohos:text="下载图片"
        ohos:background_element="#eeeeee"
        ohos:padding="20vp"
        ohos:text_size="20fp"
        />

    <RoundProgressBar
        ohos:id="$+id:round_progress_bar1"
        ohos:
        ohos:
        ohos:progress_
        ohos:top_margin="150vp"
        ohos:progress_hint_text="美女加载中"
        ohos:progress_hint_text_color="#C71585"
        ohos:layout_alignment="center"
        ohos:progress_color="#C71585"/>

    <Image
        ohos:id="$+id:image1"
        ohos:
        ohos:
        ohos:top_margin="30vp"
        ohos:layout_alignment="center"
        />

</DirectionalLayout>

这里我们先放好一个进度条RoundProgressBar,但是不让它显示。

二、AbilitySlice中的Java代码

我们在slice目录下新建一个AbilitySlice文件,FourAbilitySlice.java:

1、首先设置一下该AbilitySlice所对应的xml布局文件:

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_demo4_eventhandler_image);
        }

2、首先应该先获取xml布局中的UI控件。定义一个初始化UI控件的方法,并在onStart()中进行调用。

public class FourAbilitySlice extends AbilitySlice{
        private Image image;
    private RoundProgressBar roundProgressBar;
    private Button btn;
  
      protected void onStart(Intent intent) {
                ...
        initComponent();
    }
  
  // 获取UI组件
    private void initComponent(){
        btn= (Button) findComponentById(ResourceTable.Id_btn1);
        image = (Image) findComponentById(ResourceTable.Id_image1);
        roundProgressBar = (RoundProgressBar)findComponentById(ResourceTable.Id_round_progress_bar1);

    }
}

3、定义一个内部类DownLoadImageEventHandler用于下载图片。


    // step1:创建自定义的EventHandler子类
    //1.创建自定义的EventHandler子类
    private class DownLoadImageEventHandler extends EventHandler{

        //2.添加构造方法
        public DownLoadImageEventHandler(EventRunner runner)  {
            super(runner);
        }

        //3.重写processEvent()方法
        @Override
        protected void processEvent(InnerEvent event) {
            super.processEvent(event);


            }
        }
    }

4、创建一个方法,用于初始化EventRunner和EventHandler对象,并在onStart()中进行调用:

 //step2:示例化EventHandler和EventRunner对象,并在onStart()方法中调用该初始化方法。
    private void initHandler() {
        eventRunner = EventRunner.create("TestRunner");
        handler = new DownLoadImageEventHandler(eventRunner);
    }

onStart()方法:

protected void onStart(Intent intent) {
                ...
        initComponent();
        initHandler();
    }

5、给按钮添加点击事件,发送InnerEvent到子线程:

// 先定义全局变量
private static final int EVENT_MESSAGE_NORMAL = 1;

onStart()中为按钮添加点击事件:

                //点击按钮,下载图片
        btn.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                // step3:发送事件到子线程
                long param = 0;
                InnerEvent innerEvent = InnerEvent.get(EVENT_MESSAGE_NORMAL, param, EventRunner.current());
                handler.sendEvent(innerEvent, EventHandler.Priority.IMMEDIATE);
                System.out.println("UI线程-->InnerEvent已发送。。");
                roundProgressBar.setVisibility(Component.VISIBLE);

            }
        });

6、接下来我们就该去进行网络操作了。重写DownLoadImageEventHandler中的processEvent()方法。

我们先捋顺一下思路:
1,应该先设置一个图片地址
2,创建URL对象
3,通过HttpURLConnection链接下载图片
4,因为我们需要边下载边显示进度条,所以应该先获取图片的总长度
5,下载图片的同时,计算已经下载的数据量,除以总长度,就是进度条的百分比,我们需要将这个数据回传给UI线程,进行设置进度条。当然这一步也需要使用EventHandler对象。
6,当图片下载完毕后,我们应该将下载到的字节数组的数据,编码成一个图片对象PixelMap。
7,将图片对象回传给UI线程,显示图片,并且让进度条消失。
大概,就这么个思路

这里还要强调一下,因为目前的网络再怎么烂,下载一张图片也是嗖嗖的,所以为了能够让进度条显示一会儿,我边下载边睡眠。

以上是关于线程间通信-使用EventHandler下载网络图片的主要内容,如果未能解决你的问题,请参考以下文章

8-2 如何线程间通信

WinForms中的进程间多线程通信(网络浏览器控件)

Net线程间通信的异步机制

Linux的进程/线程间通信

Linux的进程/线程间通信

Java内存模型