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

Aion Evolution | 340 million/㎡, why is this platform so expensive?

Aluminum has long been used in aircraft manufactu...

Analysis of brand event marketing!

In recent years, the life cycle of traffic stars,...

There are many types of Internet operation jobs. How should I choose?

There are indeed many subdivisions of operations ...

How to SEO a website? A plan to increase website rights by 6 per month!

The good or bad ranking of a website is not due t...

How do information flow ads dominate HeroAPPs such as Toutiao and Weibo?

Information flow advertising first appeared on th...

Fruitwood Wanderer Intermediate and Advanced Guitar Course

Fruitwood Wanderer Intermediate and Advanced Guit...

Fed up with Windows blue screen, which Linux system is best for gaming?

Over the past few months, we have tried multiple ...

Ford conducts C-V2X test on open roads in China for the first time

From September 15 to 18, during the 2018 Wuxi Wor...

Fission! Here is a complete guide to WeChat traffic "wool wool"

1. Fission! Fission! In the past six months, fiss...

There's still half an hour before take-off, why can't I get on the plane?

When traveling by plane, many airlines recommend ...

How did cholera harm you? Which is more serious, cholera or COVID-19?

Mixed Knowledge Specially designed to cure confus...

How do educational and training institutions attract new customers online?

On May 27, I was invited by a teacher from an edu...