Note that there are some explanatory texts on larger screens.

plurals
  1. POCan onMeasure be skipped when adding a View to a ViewGroup?
    primarykey
    data
    text
    <p><strong>Answered</strong></p> <p>I have a RelativeLayout where I am adding views dynamically as the user scrolls vertically or horizontally. I have rolled my own ViewRecycler since there is potentially thousands of views that could compose the whole of what can be scrolled, but I only show 30 or so at any time. Think a zoomed in view of a calendar.</p> <p>I am running into performance problems when I add the views that are about to be seen, onMeasure is called on the RelativeLayout cascading down to onMeasure getting called on all of it's child views. I already have the calculated size of how big the RelativeLayout will ever be and have set that on it's LayoutParameters, so measuring the ViewGroup isn't necessary, nor is re-measuring the Views that have already been added with their final size and the newly added view has no bearing on those view.</p> <p>The simple example to demonstrate the problem is adding/removing a View to a RelativeLayout and watching the onMeasure get called despite the fact that it doesn't affect the RelativeLayout's size or the position of other Views.</p> <p>main.xml</p> <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/shell" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"&gt; &lt;Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content"&gt; &lt;/LinearLayout&gt; </code></pre> <p>MyActivity.java</p> <pre><code>public class MyActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ViewGroup shell = (ViewGroup) findViewById(R.id.shell); final RelativeLayout container = new RelativeLayout(this) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); Log.d("MyActvity", "onMeasure called on map"); } }; container.setBackgroundColor(Color.rgb(255, 0, 0)); ViewGroup.LayoutParams containerParams = new ViewGroup.LayoutParams(300, 300); final TextView childView = new TextView(this); childView.setBackgroundColor(Color.rgb(0, 255, 0)); childView.setText("Child View"); Button viewToggle = (Button) findViewById(R.id.button); viewToggle.setText("Add/Remove Child View"); viewToggle.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { if (childView.getParent() == null) { container.addView(childView, 400, 30); } else { container.removeView(childView); } } }); shell.addView(container, containerParams); } } </code></pre> <p>Running this, you would see 2 initial (an expected) calls to onMeasure, then one for each time that you add/remove the view by clicking the button. This obviously runs fine, but you can see where constant calls to onMeasure when you have a complex layout of nested views can get problematic.</p> <p>Is there a recommended way to bypass these onMeasure calls or at least onMeasure calling measureChildren?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload