मुख्य सामग्री पर जाएँ
CrossFly 100% ओपन सोर्सGitHub पर फ़ॉलो करें
CrossFlyCrossFly
शुरू करें
सभी उदाहरण
रेसिपीसूचियाँप्रदर्शन110 पंक्तियाँ · 1 फ़ाइलें

A list too big to build

createView is rare, bindView is constant. Anything slow in bindView — a query, a request, an allocation — is felt directly as stutter while scrolling.

यह क्या दिखाता है

Fifty thousand rows, and only a screenful of components.

An ordinary list builds one component per item. At a few hundred that is fine and simpler; at fifty thousand it allocates fifty thousand components before the first frame and the app appears to hang on open. VirtualListView keeps only what fits and recycles those as you scroll, so the cost follows the size of the window rather than the size of the data.

That is why the adapter has two methods and not one. createView builds an empty row — rarely, only when the pool runs dry. bindView fills a row that already exists, on every scroll, for every row that comes into view. Building components in bindView defeats the whole thing: it is the recycling that makes this cheap, and allocating in the bind step throws the saving away while keeping the complexity.

The price is that every row is the same height. That is what lets the list work out which items are on screen without measuring any of them, and it is the one case this cannot serve.

अपनी मशीन पर चलाएँ

हर उदाहरण एक साधारण Window है, इसलिए लॉन्चर को सिर्फ़ उसका नाम चाहिए।

gradlew lwjgl3:run --args="classname dev.cf.recipe.R17BigList"
इसे बदलना

Java पहले से संकलित होता है, इसलिए ब्राउज़र आपके बदलाव को खुद दोबारा नहीं बना सकता — यहाँ दिखा कोड प्रकाशित होने से पहले TeaVM द्वारा JavaScript में बदला गया था। फ़ाइल को किसी प्रोजेक्ट में कॉपी कीजिए और वह चारों प्लेटफ़ॉर्म पर बिना बदलाव चलती है; ऊपर दी गई कमांड ही पूरी तैयारी है।

यहीं चल रहा हैCrossFly 0.1.32
ऐप शुरू हो रहा है…

TeaVM ने इसे JavaScript में संकलित किया — यह वही कोड है, उसका वीडियो नहीं। · सभी उदाहरण

यह क्या इस्तेमाल करता है

इस उदाहरण में छुए गए फ़्रेमवर्क टाइप। जिनमें लिंक है उनका संदर्भ पृष्ठ मौजूद है।

ComponentGapGridLayoutIconBadgeLabelPalColorRelativeStylesVirtualListViewWidgets

सोर्स कोड

पूरा, बिना कटौती के। यह वही फ़ाइल है, उसका अंश नहीं।

कच्चा
dev/cf/recipe/R17BigList.java
package dev.cf.recipe;

import dev.cf.Tones;

import dev.crossfly.ui.*;
import dev.crossfly.ui.color.*;
import dev.crossfly.ui.graphics.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.style.*;

import static dev.crossfly.ui.Widgets.*;

/**
 * Fifty thousand rows, and only a screenful of components.
 *
 * <p>An ordinary list builds one component per item. At a few hundred that is fine and simpler; at
 * fifty thousand it allocates fifty thousand components before the first frame and the app appears
 * to hang on open. {@link VirtualListView} keeps only what fits and <b>recycles</b> those as you
 * scroll, so the cost follows the size of the window rather than the size of the data.</p>
 *
 * <p>That is why the adapter has two methods and not one. {@code createView} builds an empty row —
 * rarely, only when the pool runs dry. {@code bindView} fills a row that already exists, on every
 * scroll, for every row that comes into view. <b>Building components in bindView defeats the whole
 * thing</b>: it is the recycling that makes this cheap, and allocating in the bind step throws the
 * saving away while keeping the complexity.</p>
 *
 * <p>The price is that every row is the same height. That is what lets the list work out which
 * items are on screen without measuring any of them, and it is the one case this cannot serve.</p>
 */
public class R17BigList extends Recipe
{
   private static final int COUNT = 50000;

   public String title()
   {
      return "A list too big to build";
   }

   public String note()
   {
      return "createView is rare, bindView is constant. Anything slow in bindView — a query, a"
         + " request, an allocation — is felt directly as stutter while scrolling.";
   }

   /**
    * One row, holding references to the parts that change.
    *
    * <p>Keeping the labels as fields is the point: {@code bindView} then sets two strings, with no
    * tree walk and no allocation. Looking the labels up by tag on every bind would work and would
    * put a search into the scroll path.</p>
    */
   private static class Row extends Component
   {
      final Label name = label("", 1f, true, Styles.textColor, Position.START);
      final Label code = label("", 1f, false, Styles.captionColor, Position.END);
      final IconBadge tile = Tones.tile("", Tones.accent());

      Row() throws Exception
      {
         setLayout(new GridLayout(Position.START, Position.CENTER));
         getStyle().ingap(Gap.ofFont(.8f, .3f, .8f, .3f));
         add(0f, .7f, .3f, tile, outgap(name, .6f, 0, 0, 0), code);
      }

      /**
       * Repaints the tile for the row's new index.
       *
       * <p>A recycled view keeps whatever the last index left on it, so the colour has to be
       * re-bound exactly like the text is. Miss this and the list looks right until you scroll,
       * and then the tiles stop matching the numbers — the classic recycler bug, worth showing
       * in the recipe that is about recycling.</p>
       */
      void tone(int index)
      {
         PalColor t = Tones.cycle(index);
         tile.text(String.valueOf((char) ('A' + index % 26)));
         tile.getStyle()
            .backColor(t.withAlpha(0x24))
            .textColor(t);
      }
   }

   public void build(Component body) throws Exception
   {
      VirtualListView list = new VirtualListView(Relative.ofFont(3.2f),
         new VirtualListView.DataAdapter()
         {
            public int getCount()
            {
               return COUNT;
            }

            public Component createView() throws Exception
            {
               return new Row();
            }

            public void bindView(Component view, int index)
            {
               Row r = (Row) view;
               r.name.setText("Item " + (index + 1));
               r.code.setText("#" + (100000 + index));
               r.tone(index);
            }
         });
      list.testTag("recipe.biglist");
      body.add(LAY_FILL, list);
   }
}
एआई सहायक के लिए

इस पृष्ठ के मशीन-पठनीय रूप, ताकि मॉडल API का अनुमान लगाने के बजाय उदाहरण पढ़ सके।

यह उदाहरण, JSON मेंयह उदाहरण, Markdown में
पिछलाChartsअगलाStoring something