Android TextView Pre-rendering research _android

Source: Internet
Author: User
Tags drawtext

TextView in Android is one of the most complex controls in the entire framework, responsible for most of the work of displaying text in Android, and many of the controls in Framwork are directly or indirectly inherited from TextView, such as button, EditText and so on. Its internal implementation is also quite complex, the single line of code, Android-22 TextView has a full 9509 lines, in addition, TextView many operations are very heavy, such as settext operation, need to set Spanwatcher, Or you need to recreate the creation of a spannablestring, and then recreate the text Layout, which adds up to a time-consuming settext operation. In order to improve the rendering efficiency of TextView, we have recently studied the method of pre rendering, and then explained the principle.

TextView Rendering Fundamentals

First of all, introduce the basic rendering principle of TextView, in general, the TextView is responsible for rendering the text is mainly the three classes:

Boringlayout

It is primarily responsible for displaying single-line text and provides a isboring method to determine whether the criteria for a single line of text are met.

Dynamiclayout

When the text is spannable, TextView will use it to be responsible for the display of the text, set the Spanwatcher internally, and Reflow and recalculate the layout when span changes are detected.

Staticlayout

When the text is not a single line of text, and is not spannable, the use of staticlayout, the internal does not listen to span changes, so the efficiency will be higher than the dynamiclayout, only once the layout is created, But in fact the interior can also show spannablestring, but not after span changes after the layout.

In addition, all of the above three classes inherit from the layout class, in which the specific drawing of the text is unified, and in the Layout.draw method, a line of text is rendered:

Textline tl = Textline.obtain ();
 
Draw the lines, one at a time.
The baseline is the "top" of the following line minus the current line ' s descent.
for (int i = Firstline i <= lastline; i++) {
   ....
   . Directions Directions = Getlinedirections (i);
   if (directions = = Dirs_all_left_to_right &&!mspannedtext &&!hastaboremoji) {
     //Xxx:assumes there '  s nothing additional to being done
     Canvas.drawtext (buf, start, end, X, Lbaseline, paint);
   } else {
     tl.set (paint, BUF, start, end, dir, directions, Hastaboremoji, tabStops);
     Tl.draw (canvas, X, Ltop, Lbaseline, Lbottom);
   }
Textline.recycle (TL);

Can be seen for spannble, or contains emoji text, the actual rendering operation is to the textline to draw, otherwise directly using canvas.drawtext,textline responsible for the single line of complex text, which spannable, Drawing logic such as emoji is contained inside, and Textline's rendering logic is not very efficient, and the following will continue to explain how it should be optimized.

Textlayoutcache

Canvas in DrawText, if you need to calculate the size of the font every time, such as margin, etc., it will be very time-consuming, resulting in drawtext time will pull a long, in order to improve efficiency, Android introduced the Textlayoutcache after 4.0, using LRU cache cached data such as glyphs, margins, and so on, raising the DrawText speed, In 4.4, this cache size is 0.5M, global use, and will be in the activity of configurationchanged, Onresume, Lowmemory, updatevisibility and other time, Canvas.freetextlayoutcache is invoked to free this part of memory. Because this part of the cache is the bottom of the system control, we can not do specific control.

Pre-rendering optimization of TextView

From the TextView rendering principle, if we simply display the text, we do not need to set the Spanwatcher to monitor span changes, so we can directly use Boringlayout or staticlayout to directly display the text content, But Boringlayout can only display single-line text, so the best option here is to use the staticlayout directly

We chose a custom view and wanted to end up with an interface like this:

public class Staticlayoutview extends View {
  private Layout Layout = null;
  public void setlayout (Layout Layout) {
    this.layout = Layout;
    Requestlayout ();
  } 
  @Override
  protected void OnDraw (Canvas Canvas) {
    super.ondraw (Canvas);
 
    Canvas.save ();
    if (layout!= null) {
      Layout.draw (canvas, NULL, NULL, 0);
    }
    Canvas.restore ();
  }


We can draw the text directly by setting the view's layout and use the layout object directly in the OnDraw method to draw the text. Here we discard the SetText method, draw the text directly through the layout, and the layout object here, we can set it up after the creation (this can be created in a separate thread), in contrast to the normal TextView SetText method, We reduce the number of settext in the consumption, can greatly improve the efficiency.

Staticlayout is very simple to create, just a given text, width, etc. can be created directly. In addition, in order to populate the Textlayoutcache, we can also draw it in a dummy canvas after creating the Staticlayout object in advance:

Staticlayout layout = new Staticlayout (testspan.getspanstring (i), Textpaint, Hardcodewidth, Alignment, 1.0f, 0f, true);
Layout.draw (Dummycanvas);

Performance comparison

Next we test the specific performance, where the testcase are placed on the GitHub: Staticlayoutview

TestCase's content is, in a ListView, display 300 items, each item is a piece of plain text, which contains a large number of Imagespan spannablestring, on both sides of the comparison, One side is the direct use of staticlayout, one side is the use of ordinary TextView, and the 300 pieces of text is not the same, the length of different, randomly generated, in Staticlayout testcase, Staticlayout are set up in advance after another thread is created, and the spannablestring is also generated beforehand.

In addition, in order to simulate the heavy background work of real app, another 3 threads were created to try to preempt CPU resources by doing floating-point budgeting.

The measurement performance of the index, ListView continuous downward scrolling, measuring the average frame rate, measured five times, the average, the final performance test results are as follows:

Testing the machine here is MX3, the left side is the direct use of the Staticlayout scheme, the right is the system's default, y-axis is fps, you can see that the use of optimized after the scheme, the frame rate has increased a lot.

References

Improving Comment Rendering on Android

This article describes how Instagram optimizes the efficiency of their textview rendering, which is also the source of the optimization method here, Instagram is also the direct use of staticlayout and the creation of layout by the method to reduce the ListView rolling process of the drop frame rate, and the effect is very significant. This article gives an explanation of the principles here and a simple implementation

Above is to the Android TextView pre-rendering data collation, follow-up continue to supplement the relevant information, thank you for your support of this site!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.