乐趣区

关于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

退出移动版