作者:韩茹

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

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

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

后面咱们曾经搞明确了鸿蒙利用开发过程中的线程之间是如何通信的。就是利用EventHandlerInnerEventEventRunner等。

咱们想实现的内容是,点击按钮进行下载网络上的图片,图片显示前先显示进度条。当图片下载结束后,进度条隐没,显示图片。

先来看一下成果:

<img src="https://img.chengxuka.com/downloadimageyunxing1.gif" alt="downloadimageyunxing1" 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:height="match_parent"    ohos:width="match_parent"    ohos:padding="20vp"    ohos:orientation="vertical">    <Button        ohos:id="$+id:btn1"        ohos:height="match_content"        ohos:width="match_content"        ohos:text="下载图片"        ohos:background_element="#eeeeee"        ohos:padding="20vp"        ohos:text_size="20fp"        />    <RoundProgressBar        ohos:id="$+id:round_progress_bar1"        ohos:height="200vp"        ohos:width="200vp"        ohos:progress_width="10vp"        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:height="match_content"        ohos:width="match_content"        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线程,显示图片,并且让进度条隐没。大略,就这么个思路

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

示例代码:

 //3.重写processEvent()办法        @Override        protected void processEvent(InnerEvent event) {            super.processEvent(event);            if (event == null) {                return;            }            switch (event.eventId){                // step4:子线程中解决网络下载                case EVENT_MESSAGE_NORMAL:                    //下载网络图片                    try {                        System.out.println("----开始网络下载---");                        URL url = new URL(IMAGE_PATH);                        HttpURLConnection connection = (HttpURLConnection) url.openConnection();                        if(connection.getResponseCode()==HttpURLConnection.HTTP_OK){                            InputStream inputStream = connection.getInputStream();                            ByteArrayOutputStream baos = new ByteArrayOutputStream();                            //获取总长度                            long total = connection.getContentLengthLong();                            System.out.println("total---->"+total);                            byte[] bs = new byte[1024];                            int len =0;                            long sum = 0;                            //将图片回传到UI线程,设置在Image上                            EventRunner runner = (EventRunner) event.object;                            while((len=inputStream.read(bs))!=-1){                                try {                                    Thread.sleep(50);                                } catch (InterruptedException e) {                                    e.printStackTrace();                                }                                baos.write(bs, 0, len);                                sum += len;                                long percent = sum*100 / total;                                System.out.println("percent-->"+percent);                                //回传UI线程                                EventHandler eventHandler = new EventHandler(runner) {                                    @Override                                    protected void processEvent(InnerEvent event) {                                        int data = (int)event.param;                                        roundProgressBar.setProgressValue(data);                                    }                                };                                int testEventId = 1;                                long testParam = percent;                                Object testObject = null;                                InnerEvent innerEvent = InnerEvent.get(testEventId, testParam, testObject);                                eventHandler.sendEvent(innerEvent);                            }                            byte[] data = baos.toByteArray();                            System.out.println("图片数据。。"+data.length);                            //解决图片数据                            ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();                            srcOpts.formatHint = "image/png";                            ImageSource imageSource = ImageSource.create(data,srcOpts);                            ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();                            PixelMap pixelMap = imageSource.createPixelmap(decodingOpts);                            EventHandler eventHandler = new EventHandler(runner) {                                @Override                                protected void processEvent(InnerEvent event) {                                    //循环下载数据完结后:暗藏掉进度条                                    roundProgressBar.setVisibility(Component.HIDE);                                    PixelMap pixelMap = (PixelMap) event.object;                                    System.out.println("--->>>>>>>test:"+data);                                    image.setPixelMap(pixelMap);                                }                            };                            int testEventId = 1;                            long testParam = 0;                            Object testObject = pixelMap;                            InnerEvent innerEvent = InnerEvent.get(testEventId, testParam, testObject);                            eventHandler.sendEvent(innerEvent);                            System.out.println("---------");                        }                    } catch (MalformedURLException e) {                        e.printStackTrace();                    } catch (IOException e) {                        e.printStackTrace();                    }                    break;            }        }

三、设置网络拜访权限

因为咱们有拜访网络,所以要在配置文件中增加拜访网络的权限。关上config.json。

{  "app": {    "bundleName": "com.example.hanrueventhandler",    "vendor": "example",    "version": {      "code": 1000000,      "name": "1.0.0"    },    "apiVersion": {      "compatible": 4,      "target": 5,      "releaseType": "Release"    }  },  "deviceConfig": {},  "module": {    "package": "com.example.hanrueventhandler",    "name": ".MyApplication",    "deviceType": [      "phone"    ],    "distro": {      "deliveryWithInstall": true,      "moduleName": "entry",      "moduleType": "entry"    },    "abilities": [      {        "skills": [          {            "entities": [              "entity.system.home"            ],            "actions": [              "action.system.home"            ]          }        ],        "orientation": "unspecified",        "name": "com.example.hanrueventhandler.MainAbility",        "icon": "$media:icon",        "description": "$string:mainability_description",        "label": "$string:app_name",        "type": "page",        "launchType": "standard"      }    ],    "reqPermissions": [      {        "name": "ohos.permission.GET_NETWORK_INFO"      },      {        "name": "ohos.permission.INTERNET"      },      {        "name": "ohos.permission.SET_NETWORK_INFO"      }    ]  }}

最初几行就是网络的权限了。

最初批改一下程序的入口:

public class MainAbility extends Ability {    @Override    public void onStart(Intent intent) {        super.onStart(intent);        super.setMainRoute(FourAbilitySlice.class.getName());//要显示的哪个AbilitySlice    }}