如何解決快應用頁面滑動卡頓問題


問題現象

頁面一次加載了100條數據,頁面滑動出現卡頓。

問題代碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
<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;
     #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;
     #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部分):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<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/consumer/cn/doc/development/quickApp-References/quickapp-component-list#h1-1592485335262

 

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM