Android uses ViewStub to improve layout performance

Android uses ViewStub to improve layout performance

[[171874]]

In Android development, View is a technology that we must use for display. Usually, as the View becomes more and more complex, the performance of the overall layout will also decrease. Here is a View that improves layout performance in some scenarios, which is ViewStub.

What is ViewStub

  • ViewStub is a subclass of View
  • It is invisible and has a size of 0
  • Used to delay loading of layout resources

Note: Explanation of Stub

A stub is a small program routine that substitutes for a longer program, possibly to be loaded later or that is located remotely

In Java, a stub is code that replaces associated code or unimplemented code.

ViewStub usage scenarios

As shown in the figure above,

  • A ListView contains items such as news, business, technology, etc.
  • Each Item contains its own corresponding sub-topic.
  • However, the subtopic View (blue area) only needs to be loaded when the expand button is clicked.
  • If the subtopic View is loaded by default, it will cause memory usage and CPU consumption

So, ViewStub comes in handy at this time. Using ViewStub can delay loading layout resources.

How to use ViewStub

1. Use the ViewStub tag in the layout file

  1. <? xml   version = "1.0"   encoding = "utf-8" ?>  
  2. < RelativeLayout  
  3. xmlns:android = "http://schemas.android.com/apk/res/android"  
  4. xmlns:tools = "http://schemas.android.com/tools"  
  5. android:layout_width = "match_parent"  
  6. android:layout_height = "match_parent"  
  7. android:paddingLeft = "@dimen/activity_horizontal_margin"  
  8. android:paddingRight = "@dimen/activity_horizontal_margin"  
  9. android:paddingTop = "@dimen/activity_vertical_margin"  
  10. android:paddingBottom = "@dimen/activity_vertical_margin"  
  11. tools:context = "com.droidyue.viewstubsample.MainActivity" >  
  12.  
  13. < Button  
  14. android:id = "@+id/clickMe"  
  15. android:text = "Hello World!"  
  16. android:layout_width = "wrap_content"  
  17. android:layout_height = "wrap_content" />  
  18.      
  19. < ViewStub  
  20. android:id = "@+id/myViewStub"  
  21. android:inflatedId = "@+id/myInflatedViewId"  
  22. android:layout = "@layout/include_merge"  
  23. android:layout_width = "wrap_content"  
  24. android:layout_height = "wrap_content"  
  25. android:layout_below = "@id/clickMe"  
  26. />  
  27. </RelativeLayout>  

2. Inflate layout in code

  1. ViewStub myViewStub = (ViewStub)findViewById(R.id.myViewStub);
  2. if (myViewStub != null) {
  3. myViewStub.inflate();
  4. //Or load it in the following form
  5. //myViewStub.setVisibility(View.VISIBLE);
  6. }

About ViewStub

  • In addition to the inflate method, we can also call the setVisibility() method to load the layout file.
  • Once the layout is loaded, the ViewStub will be removed from the current layout hierarchy.
  • android:id specifies the ViewStub ID, which is used to find the ViewStub for lazy loading
  • android:layout delays loading of layout resource id
  • android:inflatedId The id of the loaded layout is overwritten, here is the id of RelativeLayout

Disadvantages of ViewStub

There is such a description in the official document

Note: One drawback of ViewStub is that it doesn't currently support the tag in the layouts to be inflated.

This means that ViewStub does not support Label.

About not supporting To verify the degree of labeling, we conduct a simple verification

Verification 1: Direct labeling

As follows, we have a layout file named merge_layout.xml

  1. < merge   xmlns:android = "http://schemas.android.com/apk/res/android" >  
  2.  
  3. < Button              android:layout_width = "fill_parent"  
  4. android:layout_height = "wrap_content"  
  5. android:text = "Yes" />  
  6.  
  7. < Button              android:layout_width = "fill_parent"  
  8. android:layout_height = "wrap_content"  
  9. android:text = "No" />  
  10.  
  11. </ merge >  

After replacing the android:layout attribute value of the corresponding ViewStub, the following crash is generated after running (clicking the Button button)

  1. E AndroidRuntime: android.view.InflateException: Binary XML file line #1: < merge   /> can be used only with a valid ViewGroup root and attachToRoot = true  
  2. E AndroidRuntime: at android.view.LayoutInflater.inflate(LayoutInflater.java:551)
  3. E AndroidRuntime: at android.view.LayoutInflater.inflate(LayoutInflater.java:429)
  4. E AndroidRuntime: at android.view.ViewStub.inflate(ViewStub.java:259)
  5. E AndroidRuntime: at com.droidyue.viewstubsample.MainActivity$1.onClick(MainActivity.java:20)
  6. E AndroidRuntime: at android.view.View.performClick(View.java:5697)
  7. E AndroidRuntime: at android.widget.TextView.performClick(TextView.java:10815)
  8. E AndroidRuntime: at android.view.View$PerformClick.run(View.java:22526)
  9. E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:739)
  10. E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:95)
  11. E AndroidRuntime: at android.os.Looper.loop(Looper.java:158)
  12. E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:7237)
  13. E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
  14. E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
  15. E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
  16. E AndroidRuntime: Caused by: android.view.InflateException: < merge   /> can be used only with a valid ViewGroup root and attachToRoot = true  
  17. E AndroidRuntime: at android.view.LayoutInflater.inflate(LayoutInflater.java:491)
  18. E AndroidRuntime: ... 13 more

Visible, direct Tags and ViewStub are not supported.

Verify the indirect ViewStub

The following layout indirectly uses the merge tag. The file name is include_merge.xml

  1. <? xml   version = "1.0"   encoding = "utf-8" ?>  
  2. < LinearLayout   xmlns:android = "http://schemas.android.com/apk/res/android"  
  3. android:orientation = "vertical"  
  4. android:layout_width = "match_parent"  
  5. android:layout_height = "match_parent" >  
  6. < include   layout = "@layout/merge_layout" />  
  7. </LinearLayout>  

Then modify the android:layout value of ViewStub and run it. Everything should be normal.

In addition, this example also verifies that ViewStub is also Good tag support.

A little code analysis about ViewStub

inflate vs setVisibility

The common point between inflate and setVisibility is that they can both load layouts

  1. /** * When visibility is set to {@link #VISIBLE} or {@link #INVISIBLE},
  2. * {@link #inflate()} is invoked and this StubbedView is replaced in its parent
  3. * by the inflated layout resource.
  4. *
  5. * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
  6. *
  7. * @see #inflate()
  8. */
  9. @Override
  10. public void setVisibility(int visibility) {
  11. if (mInflatedViewRef != null) {
  12. View view = mInflatedViewRef .get();
  13. if (view != null) {
  14. view.setVisibility(visibility);
  15. } else {
  16. throw new IllegalStateException("setVisibility called on un-referenced view");
  17. }
  18. } else {
  19. super.setVisibility(visibility);
  20. if ( visibility == VISIBLE || visibility == INVISIBLE) {
  21. inflate();
  22. }
  23. }
  24. }

setVisibility only calls the inflate method when ViewStub is first lazily initialized and visibility is not GONE.

inflate source code

By reading the following inflate method implementation, we will better understand

  • Purpose of android:inflatedId
  • ViewStub is removed from the view hierarchy after initialization.
  • ViewStub layoutParameters application
  • mInflatedViewRef establishes the connection between ViewStub and the loaded View through weak reference.

  1. /** * Inflates the layout resource identified by {@link #getLayoutResource()}
  2. * and replaces this StubbedView in its parent by the inflated layout resource.
  3. *
  4. * @return The inflated layout resource.
  5. *
  6. */
  7. public View inflate() {
  8. final ViewParent viewParent = getParent ();
  9.  
  10. if (viewParent != null && viewParent instanceof ViewGroup) {
  11. if (mLayoutResource != 0) {
  12. final ViewGroup parent = (ViewGroup) viewParent;
  13. final LayoutInflater factory = LayoutInflater .from(mContext);
  14. final View view = factory .inflate(mLayoutResource, parent,
  15. false);
  16.  
  17. if (mInflatedId != NO_ID) {
  18. view.setId(mInflatedId);
  19. }
  20.  
  21. final int index = parent .indexOfChild(this);
  22. parent.removeViewInLayout(this);
  23.  
  24. final ViewGroup.LayoutParams layoutParams = getLayoutParams ();
  25. if (layoutParams != null) {
  26. parent.addView(view, index, layoutParams);
  27. } else {
  28. parent.addView(view, index);
  29. }
  30.  
  31. mInflatedViewRef = new WeakReference < View > (view);
  32.  
  33. if (mInflateListener != null) {
  34. mInflateListener.onInflate(this, view);
  35. }
  36.  
  37. return view;
  38. } else {
  39. throw new IllegalArgumentException("ViewStub must have a valid layoutResource");
  40. }
  41. } else {
  42. throw new IllegalStateException("ViewStub must have a non-null ViewGroup viewParent");
  43. }
  44. }

<<:  Guide for the National Day holiday, Youji uses VR to give you a different kind of fun

>>:  ASUS's unique aesthetics of technology and art

Recommend

In-depth analysis: the underlying logic of user needs

In the ups and downs of the business world, there...

Guiyang sauna bath, tea tasting massage, what services do you know?

Guiyang sauna and bath, do you know what services...

Wentian Laboratory, what is it going to do in space?

Mixed Knowledge Specially designed to cure confus...

The classic "flash" is reborn in "Glitter Pac-Man" with a new experience

Screen: operate: Sound Effects: Plot: Experience:...

The internationalization of Chinese home appliances is mostly forced

What is the overseas gold rush, broad prospects, ...

How do educational platforms acquire customers at low cost?

Under the epidemic, the market investment cost of...

Has your information been leaked today?

Today is an information age. Data is considered t...

Which promotional platforms are suitable for Father’s Day marketing ads?

June 16th is Father's Day, and there are stil...

Low-power M2M market is vast. How to reduce power consumption in chip design?

The topic of the Internet of Things is currently ...

Trivia | Eight must-check websites before getting married

One minute with the doctor, the postures are cons...