Any tips to improve TableListBox mobile performance

Hi there,

I’m aware this issue has been brought up a few times here and there. Although I’d like to check in with you guys hoping that my info is simply outdated and there is a magical new way of doing things.

Reading through various threads I have already implemented drawing components on open GL and taking advantage of image caching.

My global caching method looks like this:

auto MainLook::make_text_image(const String& text, const Colour& colour, const Font& font,
                               const int width, const int height,
                               const CacheSource source) noexcept-> Image
{
    auto stream = MemoryOutputStream{};
    stream << text << static_cast<int64>(colour.getARGB()) << static_cast<uint_f8>(source);
    const auto hash = stream.toString().hashCode64();
    
    auto img = ImageCache::getFromHashCode(hash);
    
    if (! img.isValid()) {
        
        img = Image{ Image::ARGB, width, height, true };
        auto g = Graphics{ img };
        g.setColour(colour);
        g.setFont(font.withHeight(0.5f * height));
        g.drawText(text, 0, 0, width, height, Justification::centredLeft, true);
        
        ImageCache::addImageToCache(img, hash);
    }
    
    return img;
}

And in paint methods that need this such as TableListBox::paintCell(), it is called like so:

    void paintCell(Graphics& g, int row_no, int column_id, int width, int height,
                   bool row_is_selected) override
    {   // Paints any cells that aren't using custom components
        // (copied from the JUCE TableListBoxModel tutorial).
        
        const auto& look = static_cast<MainLook&>(table_view.getLookAndFeel());
        
        if (const auto* row = item_xml(row_no)) {
            
            const auto& cell_text = row->getStringAttribute(tree_id_str(column_id));
            const auto& text_colour =    is_selectable
                                      && row_is_selected ? look.black[0] :
                                                           look.white[0];
            const auto img = look.make_text_image(cell_text, text_colour, look.roboto_light,
                                                  width - get_margin(), height,
                                                  CacheSource::tree_table);
            g.drawImageAt(img, get_margin(), 0);
        }
        
        // Column lines
        g.setColour(look.black[5]);
        g.drawVerticalLine(width - 1, 0, height);
    }

Some details about the table:

  • no custom components, i.e. using the paintCell() override.
  • 5 columns, 12 visible rows out of 50 - 100 entries
  • This is ~60 visible cells at any one time.
  • row background drawing contains some code to colour odd, even and selected rows differently.

Even using these techniques, the performance is still very bad.
To clarify, the performance is pretty good when this single line is removed from paintCell():
g.drawImageAt(img, get_margin(), 0);

Many thanks in advance for your help.

On further inspection and benchmarking, I discovered other interfering parts of code that influenced performance here. I’m going to close this thread as these issues are likely to be solved.

Myself and others on here tried to solve this, but no one that I know of came up with a satisfactory solution. My recommendation is to use native components, if you want smooth scrolling.

3 Likes