关于appgallery-connect:如何解决快应用页面滑动卡顿问题

问题景象

页面一次加载了100条数据,页面滑动呈现卡顿。

问题代码

<template>
  <div class="container">
    <div class="nav">
      <text class="nav-item">list</text>
    </div>
 
    <!-- List -->
    <list class="list" onclick="listClick" onlongpress="listLongPress"
      onscrollbottom="scrollbottom"  id="list" scrollpage="{{scrollPage}}">
 
      <list-item type="listItem" class="item"  onclick="listItemClick"
        if="{{listData.length>0}}">
           <div for="{{listData}}" style="flex-direction:column;">
                <text  class="txt">{{$item}}--{{$idx}}</text>
           </div>
      </list-item>
 
      <!-- Loading More  -->
      <list-item type="loadMore" class="load-more" if="{{loadMore}}">
        <progress type="circular"></progress>
        <text>More</text>
      </list-item>
    </list>
 
  </div>
</template>
<style>
 
  .container{
     flex-direction: column;
  }
 
  .list {
    padding-left: 10px;
    padding-right: 10px;
    columns: 1;
    flex-direction: column;
    border-color: #FF0000;
    border-width: 5px;
  }
 
  .item {
    flex-direction: column;
    align-items: flex-start;
    margin-bottom: 15px;
    border-color: #9400D3;
    border-width: 5px;
    margin-right: 20px;
    background-color: #f76160;
  }
 
  .load-more {
    justify-content: center;
    align-items: center;
    height: 100px;
    border-color: #bbbbbb;
    border-bottom-width: 1px;
  }
 
  .btn-little {
    flex: 1;
    height: 80px;
    margin-left: 15px;
    border-radius: 5px;
    color: #ffffff;
    font-size: 30px;
    text-align: center;
    background-color: #0faeff;
  }
 
  .nav {
    padding-left: 60px;
    padding-right: 60px;
    padding-bottom: 30px;
  }
 
  .nav-item {
    flex: 1;
    padding-bottom: 30px;
    border-bottom-width: 5px;
    border-color: #fbf9fe;
    font-size: 35px;
    color: #666666;
    text-align: center;
  }
 
</style>
<script>
  import prompt from '@system.prompt'
 
  export default {
    data: {
      componentName: 'list',
      loadMore: true,
      listAdd: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
      listData: [],
      scrollPage: false,
    },
    onInit: function () {
      this.$page.setTitleBar({ text: 'list' })
      for(var index = 0;index < 100;index++){
          this.listData[index] = 'A';
     }
      
    },
  
    scrollbottom: function () {
      prompt.showToast({
        message: 'The list slides to the bottom and starts loading other data.'
      })
      // Load next page
      var that = this
      var renderData = [].concat(that.listData, that.listAdd)
      setTimeout(function () {
        that.listData = renderData
      }, 1000)
    },
 
    // monitoring during sliding
    scroll: function (e) {
      let msg = 'scroll' + '.scrollX:' + e.scrollX
        + ' .scrollY:' + e.scrollY
        + ' .scrollState:' + e.scrollState
      console.info(msg)
    },
  
  
    listItemClick: function (e) {
      e.stopPropagation()
      console.info('List Item is clicked.')
      prompt.showToast({
        message: 'List Item is clicked.'
      })
    },
    listClick: function (e) {
      e.stopPropagation()
      console.info('List is clicked.')
      prompt.showToast({
        message: 'List is clicked.'
      })
    },
 
    listLongPress: function (e) {
      e.stopPropagation()
      console.info('List is long pressed.')
      prompt.showToast({
        message: 'List is long pressed.'
      })
    },
  }
</script>

问题剖析
以上代码应用list、list-item来加载大规模数据,然而应用办法不当,导致list-item的视图view没有被复用。

咱们晓得快利用的引擎是一个android apk,list、list-item的实现最终都是通过android的ListView、BaseAdapter等这些实现的,理解这些其实晓得列表界面上超过屏幕显示的区域是不会从新创立视图的,而是复用第一次在界面上可见区域的那些view的,只须要把数据刷新一下即可。每一行的视图view其实就是list-item。

以上代码尽管看起来是列表,然而只有1个list-item,开发者在list-item外部应用了for循环,每循环一次,都会创立一个新的view,当数据量很大时,内存占用越多,手机内存吃紧,一直地做申请、开释内存的操作,利用性能受到重大影响,导致滑动卡顿。

解决办法
基于list组件的特点,在list-item外部外部需谨慎应用if指令或for指令,依据列表每行数据特点,在list-item上设置不同的type,尽可能复用list-item,在list-item上应用for语句。批改后代码如下(留神list-item局部):

<template>
  <div class="container">
    <div class="nav">
      <text class="nav-item">list</text>
    </div>
 
    <!-- List -->
    <list class="list" onclick="listClick" onlongpress="listLongPress"
      onscrollbottom="scrollbottom"  id="list" scrollpage="{{scrollPage}}">
     
      <list-item type="listItem" class="item item-color"  onclick="listItemClick"
        for="{{listData}}">
        <text  class="txt">{{$item}}--{{$idx}}</text>
      </list-item>
 
      <!-- <list-item type="listItem" class="item"  onclick="listItemClick"
        if="{{listData.length>0}}">
           <div for="{{listData}}" style="flex-direction:column;">
                <text  class="txt">{{$item}}--{{$idx}}</text>
           </div>
      </list-item> -->
 
      <!-- Loading More  -->
      <list-item type="loadMore" class="load-more" if="{{loadMore}}">
        <progress type="circular"></progress>
        <text>More</text>
      </list-item>
    </list>
 
  </div>
</template>

代码运行效果图比照:


图1 批改后成果


图2 批改前成果

从下面效果图中咱们看到,尽管都是列表数据,然而图1每一行都是一个list-item(list-item的css中背景色设置的是红色),而且type值都一样,能很好地复用list-item,然而图2中只有1个list-item,外面列表数据都是作为list-item的子节点。图2的成果和应用一般的div加载大量列表数据是一样的,本源在于开发者没有很好地了解list、list-item的原理。

欲了解更多详情,请参见:

快利用list开发领导:

https://developer.huawei.com/…

原文链接:https://developer.huawei.com/…
原作者:Mayism

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理