Respondido¿Se puede omitir Can onMeasure al agregar una vista a un grupo de visualización?
Tengo un RelativeLayout donde estoy añadiendo vistas dinámicamente a medida que el usuario se desplaza verticalmente u horizontalmente. He rodado mi propio ViewRecycler ya que hay potencialmente miles de vistas que podrían componer todo lo que se puede desplazar, pero solo muestro 30 más o menos en cualquier momento. Piensa en un zoom a la vista de un calendario.
Me encuentro con problemas de rendimiento cuando agrego las vistas que están a punto de verse, onMeasure se invoca en RelativeLayout en cascada hasta que onMeasure recibe una llamada en todas sus vistas secundarias. Ya tengo el tamaño calculado de cuán grande será RelativeLayout y lo he configurado en sus parámetros de diseño, por lo que no es necesario medir ViewGroup, ni volver a medir las vistas que ya se han agregado con su tamaño final y el nuevo la vista añadida no tiene relación con esa vista.
El ejemplo simple para demostrar el problema es agregar/eliminar una Vista a una RelativeLayout y ver llamar a onMeasure a pesar de que no afecta el tamaño de RelativeLayout ni la posición de otras Vistas.
main.xml
<?xml version="1.0" encoding="utf-8"?>
<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">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</LinearLayout>
MyActivity.java
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);
}
}
La ejecución de este, que se vería 2 inicial (un esperado) llama a onMeasure, a continuación, una por cada vez que agrega/quita la vista haciendo clic en el botón. Obviamente, esto funciona bien, pero puede ver que las llamadas constantes a onMeasure cuando tiene un diseño complejo de vistas anidadas pueden ser problemáticas.
¿Hay alguna forma recomendada de evitar estas llamadas en Measure o al menos en Measure llamando a measureChildren?
Respondido en android-developers: http://groups.google.com/group/android-developers/browse_frm/thread/5951029333032455 – CommonsWare
Gracias Marque para el enlace cruzado. Actualicé la publicación original con mi solución más rápida/más sucia. –
¿Puedes responder a tu propia pregunta de una manera que pueda ayudar a los demás?Solo edite la "solución" de su pregunta y agréguela como una nueva respuesta. Una vez que lo haga, puede seleccionar el suyo como la respuesta correcta. Puede parecer extraño, pero es la forma preferida de lidiar con situaciones como esta. – Will