How to update some data in a Listview without using notifyDataSetChanged()?

后端 未结 3 1392
野的像风
野的像风 2020-12-07 16:51

I\'m trying to create a ListView with a list of downloading tasks.

The downloading tasks are managed in a Service (DownloadService). Everyt

3条回答
  •  醉酒成梦
    2020-12-07 17:48

    The short answer: dont update the UI based on data speeds

    Unless you are writing a speed test style app, there is no user benefit to updating this way.

    ListView is very well optimized, (as you seem to already know because you are using the ViewHolder pattern).

    Have you tried calling notifyDataSetChanged() every 1 second?

    Every 1024 bytes is ridiculously fast. If someone is downloading at 8Mbps that could be updating over 1000 times a second and this could definitely cause an ANR.

    Rather than update progress based on amount downloaded, you should poll the amount at an interval that does not cause UI blocking.

    Anyways, in order to help avoid blocking the UI thread you could post updates to a Handler.

    Play around with the value for sleep to be sure you are not updating too often. You could try going as low as 200ms but I wouldn't go below 500ms to be sure. The exact value depends on the devices you are targeting and number of items that will need layout passes.

    NOTE: this is just one way to do this, there are many ways to accomplish looping like this.

    private static final int UPDATE_DOWNLOAD_PROGRESS = 666;
    
    Handler myHandler = new Handler()
    {
        @Override
        handleMessage(Message msg)
        {
            switch (msg.what)
            {
                case UPDATE_DOWNLOAD_PROGRESS:
                    myAdapter.notifyDataSetChanged();
                    break;
                default:
                    break;
            }
        }
    }
    
    
    
    private void runUpdateThread() { 
        new Thread(
         new Runnable() {
             @Override
             public void run() {
                 while ( MyFragment.this.getIsDownloading() )
                 {
                      try 
                      {    
                          Thread.sleep(1000); // Sleep for 1 second
    
                          MyFragment.this.myHandler
                              .obtainMessage(UPDATE_DOWNLOAD_PROGRESS)
                              .sendToTarget();
                      } 
                      catch (InterruptedException e) 
                      {
                          Log.d(TAG, "sleep failure");
                      }
                 }
    
             }
         } ).start(); 
    }
    

提交回复
热议问题