鸿蒙应用开发之ListContainer

epeppanda
发布于 2021-4-30 19:19
浏览
0收藏

前言


本文主要介绍鸿蒙应用开发中的ListContainer控件的使用,其中涉及以下几个鸿蒙sdk的知识点。

  • ListContainer
  • TaskDispatcher
  • EventHandler
    我们废话不多说,直接进入正题。

 

ListContainer


ListContainer等同于Android中的Listview,将会是以后我们日常开发最常使用的控件之一。为什么说等同于Listview呢?不仅是因为效果基本一致,连Api的设计和代码实现都基本一致,上代码

ListItemProvider.java

public class ListItemProvider extends RecycleItemProvider {

    private List<String> data;
    private Context context;
    private LayoutScatter scatter;

    public ListItemProvider(Context context, List<String> data) {
        this.context = context;
        this.data = data;
        this.scatter = LayoutScatter.getInstance(context);
    }

    @Override
    public int getCount() {
        return data != null ? data.size() : 0;
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public Component getComponent(int i, Component component, ComponentContainer componentContainer) {
        System.out.println("ListItemProvider-getComponent-" + i);
        ViewHolder viewHolder = null;
        if (component == null) {
            component = scatter.parse(ResourceTable.Layout_list_item, null, false);
            viewHolder = new ViewHolder((ComponentContainer) component);
            component.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) component.getTag();
        }

        viewHolder.left.setText(data.get(i));
        viewHolder.right.setText(data.get(i));

        return component;
    }

    static class ViewHolder {
        Text left;
        Text right;

        public ViewHolder(ComponentContainer container) {
            left = (Text) container.findComponentById(ResourceTable.Id_left);
            right = (Text) container.findComponentById(ResourceTable.Id_right);
        }
    }
}

 

这个类的实现是不是似曾相识?不就是Listview的Adapter嘛,当然这和官方的demo写法不一样,但是这么写,android的同学估计一分钟就能理解了。ListContainer基本照搬了Listview的控件设计,包括Listview模版复用特性。


list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos"
                   ohos:width="match_parent"
                   ohos:height="match_parent"
                   ohos:orientation="horizontal">

    <DependentLayout
            ohos:width="0"
            ohos:height="match_parent"
            ohos:weight="1"
            ohos:background_element="#ff0000"
            >

        <Text
                ohos:id="$+id:left"
                ohos:width="match_content"
                ohos:height="match_content"
                ohos:text_size="16vp"
                ohos:text_color="#ffffff"
                ohos:center_in_parent="true"
                />

    </DependentLayout>

    <DependentLayout
            ohos:width="0"
            ohos:height="match_parent"
            ohos:weight="1"
            ohos:background_element="#0000ff"
            >

        <Text
                ohos:id="$+id:right"
                ohos:width="match_content"
                ohos:height="match_content"
                ohos:text_size="26vp"
                ohos:text_color="#ffffff"
                ohos:center_in_parent="true"
                />

    </DependentLayout>


</DirectionalLayout>

这是item的布局文件,不做展开。

 

list.xml

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos"
                   ohos:width="match_parent"
                   ohos:height="match_parent"
                   ohos:orientation="vertical">

    <ListContainer
            ohos:id="$+id:list"
            ohos:width="match_parent"
            ohos:height="match_parent"
            />

</DirectionalLayout>

 

这是主布局文件,比较简单,就是ListContainer的声明。

 

MainAbilitySlice.java

public class MainAbilitySlice extends AbilitySlice {

    private ListContainer listContainer;
    private ListItemProvider itemProvider;
    private List<String> data = new ArrayList<>();

    //关联子线程
    private EventHandler handler = new EventHandler(EventRunner.create(true));

    //关联UI线程
    private EventHandler handler2 = new EventHandler(EventRunner.current()) {
        @Override
        protected void processEvent(InnerEvent event) {
            super.processEvent(event);
            System.out.println("2-" + Thread.currentThread().getName());
            if (event.eventId == 0) {
                itemProvider.notifyDataChanged();
            }
        }
    };

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_list);
        //1.通过id找到控件实例
        listContainer = (ListContainer) findComponentById(ResourceTable.Id_list);
        //2.创建Provider实例
        itemProvider = new ListItemProvider(this, data);
        //3.将Provider和ListContainer绑定
        listContainer.setItemProvider(itemProvider);
        //4.设置item的点击监听
        listContainer.setItemClickedListener(new ListContainer.ItemClickedListener() {
            @Override
            public void onItemClicked(ListContainer listContainer, Component component, int i, long l) {

            }
        });
        //模拟真实的耗时获取数据,再更新UI
        //方式1:使用EventHandler完成线程间的通信
        handler.postTask(new Runnable() {
            @Override
            public void run() {
                System.out.println("1-" + Thread.currentThread().getName());
                List<String> temp = new ArrayList<>();
                for (int i = 0; i < 30; i++) {
                    temp.add("" + (i + 1));
                }
                data.addAll(temp);
                itemProvider.notifyDataChanged();
            }
        }, 3000);
        //方式2:使用EventHandler和TaskDispatcher配合
        createParallelTaskDispatcher("123", TaskPriority.DEFAULT).delayDispatch(new Runnable() {
            @Override
            public void run() {
                System.out.println("1-" + Thread.currentThread().getName());
                List<String> temp = new ArrayList<>();
                for (int i = 0; i < 30; i++) {
                    temp.add("" + (i + 1));
                }
                data.addAll(temp);
                handler2.sendEvent(0);
            }
        }, 3000);
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
}

 

MainAbilitySlice相当于Fragment,最终的实现在这里。重要的步骤已经注释了,也基本上是Listview的使用流程。其实到这里,简单的ListContainer已经完成了,我们这里再简单介绍下EventHandler和TaskDispatcher。

 

EventHandler


EventHandler在官方文档中篇幅不小,从使用角度,它就是android中的handler,当然其背后的原理可能不一样,还没研究过(估计大同小异),但是使用完全可以参照handler,看下我上面的代码,是不是就是handler的写法。详细介绍下次专门写篇介绍。

 

TaskDispatcher


看到这里,感觉鸿蒙的这些api都和android极其相似,那TaskDispatcher像是android中的什么呢?还真没有它的兄弟,它更像是android中asynctask的替代,但是设计和使用都天差地别。 官方解释:TaskDispatcher是一个任务分发器,它是Ability分发任务的基本接口,隐藏任务所在线程的实现细节。以下是TaskDispatcher的几种实现。

 

  • GlobalTaskDispatcher:全局并发任务分发器,由Ability执行getGlobalTaskDispatcher()获取。适用于任务之间没有联系的情况。一个应用只有一个
  • GlobalTaskDispatcher,它在程序结束时才被销毁。
  • ParallelTaskDispatcher:并发任务分发器,由Ability执行createParallelTaskDispatcher()创建并返回。与GlobalTaskDispatcher不同的是,ParallelTaskDispatcher不具有全局唯一性,可以创建多个。开发者在创建或销毁dispatcher时,需要持有对应的对象引用 。
  • SerialTaskDispatcher:串行任务分发器,由Ability执行createSerialTaskDispatcher()创建并返回。由该分发器分发的所有的任务都是按顺序执行,但是执行这些任务的线程并不是固定的。如果要执行并行任务,应使用ParallelTaskDispatcher或者GlobalTaskDispatcher,而不是创建多个SerialTaskDispatcher。如果任务之间没有依赖,应使用GlobalTaskDispatcher来实现。它的创建和销毁由开发者自己管理,开发者在使用期间需要持有该对象引用。
  • SpecTaskDispatcher:专有任务分发器,绑定到专有线程上的任务分发器。目前已有的专有线程是主线程。UITaskDispatcher和MainTaskDispatcher都属于SpecTaskDispatcher。建议使用UITaskDispatcher。


UITaskDispatcher:绑定到应用主线程的专有任务分发器, 由Ability执行getUITaskDispatcher()创建并返回。 由该分发器分发的所有的任务都是在主线程上按顺序执行,它在应用程序结束时被销毁。

 

上面的文字都是官方文档上的,就是想告诉你这些知识点。这里先不展开,简单理解,他就是一个任务分发绑定着一个线程池,来帮助应用开发者简便的完成异步任务。

 

总结


支持鸿蒙,支持鸿蒙生态。这是真国货,想交朋友的,大家交个朋友,一起学习进步,写的不好,请见谅。

 

 

 

 

 

 

 

 

作者:暗影萨满

分类
已于2021-4-30 19:19:05修改
收藏
回复
举报
回复
    相关推荐