¿Cuál es la forma más rápida de agregar varias vistas a un LinearLayout?

Tengo una vista LinearLayout que ya contiene varios elementos. Quiero agregar mucho más vistas a él, programmatically. Y debido a que esto está dentro de un ScrollView , todo se desplazará.

Así que lo que hago es ir a través de mi lista, y añadir nuevas instancias de mi personalizado Ver a ella. Esa vista personalizada infla un diseño XML y añade algunos métodos.

Este enfoque funciona bien. El problema es que es súper lento, incluso sin ningún código loco … una lista con 10 elementos tarda unos 500 ms para crear instancias. Como punto de vista de la experiencia del usuario, esto es difícil de tragar.

Mi pregunta es, ¿es este el enfoque correcto / mejor? Android parece tardar mucho tiempo en inflar el diseño, aunque "R.layout.my_list_item" es super simple. Me pregunto si hay una manera de tal vez para reutilizar "inflado" diseños de vistas adicionales, un poco de almacenamiento en caché el análisis más complejo?

He intentado hacer esto con un ListView (y el adaptador y un envoltorio) y parece ser mucho más rápido. El problema es que no puedo usar un ListView simple; mi diseño es más complejo que una simple lista (el propio LinearLayout contiene iconos personalizados adicionales y tiene otro padre con vistas aún más antes de que esté envuelto por el ScrollView ).

¿Pero hay una manera de utilizar un adaptador para un LinearLayout? ¿Sería eso más rápido que intentar agregar las vistas yo mismo?

Cualquier ayuda es apreciada. Me encantaría hacer esto más rápido.

El código sigue.

Actividad principal:

 // The LinearLayout that will contain everything lineList = (LinearLayout) findViewById(R.id.lineList); // Add a lot of items for testing for (int i = 0; i < 10; i++) { addListItem("Item number " + i); } protected void addListItem(String __title) { MyListItem li; li = new MyListItem(this); li.setTitle(__title); lineList.addView(li); } 

MyListItem:

 public class MyListItem extends RelativeLayout { protected TextView textTitle; public MyListItem(Context __context) { super(__context); init(); } public MyListItem(Context __context, AttributeSet __attrs) { super(__context, __attrs); init(); } public MyListItem(Context __context, AttributeSet __attrs, int __attrsdefStyle) { super(__context, __attrs, __attrsdefStyle); init(); } protected void init() { // Inflate the XML layout LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); inflater.inflate(R.layout.my_list_item, this); // Create references textTitle = (TextView)findViewById(R.id.textTitle); } public void setTitle(String __text) { textTitle.setText(__text); } } 

Lo que estoy tratando de lograr es esto. Considere esta disposición:

Diseño básico

Este diseño es un FrameLayout (cuadro exterior) que contiene un ImageView (en gris), un TextView (rectángulo interior, en la parte superior) y un LinearLayout (rectángulo interior, en la parte inferior). Este rectángulo LinearLayout es el que estoy poblando dinámicamente con unos pocos elementos.

Después de que lo MyListItem , quiero que el resultado final sea este (donde cada nuevo rectángulo es una nueva instancia de MyListItem ):

Disposición poblada

Es decir, todo es desplazable (la imagen de fondo, por ejemplo, está alineada en la parte superior). El LinearLayout no es desplazable por sí mismo (todo lo demás sigue) por lo que un ListView , de lo que sé, no funcionaría muy bien en mi caso.

3 Opciones:

  1. Reemplace todo con un ListView, con el otro padre y los iconos personalizados como una vista de encabezado para el ListView. ListView es más rápido, ya que sólo crea Vistas según las necesidades.

  2. Programe crear el contenido de my_list_item en lugar de inflar, podría ser más rápido

  3. El uso de ViewStubs puede permitirle cargar vistas bajo demanda.

  4. Tal vez no es la carga de las vistas, pero los datos? en cuyo caso preparar los datos en un hilo de fondo.

Un ListView es el camino a seguir.

Usted dice que su diseño es demasiado complejo. Pero está completamente bien inflar un diseño complejo como un niño. Por ejemplo un diseño que tiene texto y luego un icono:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> 

Se podría inflar en su adaptador como tal:

 @Override public View getView(final int position, View convertView, ViewGroup parent) { LinearLayout root = null; ImageView editImageView; if (convertView == null) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); root = (LinearLayout)inflater.inflate(R.layout.item, null); } else { root = (LinearLayout)convertView; } } 

También puede ser un poco más inteligente con el fin de apoyar una cabecera. Simplemente agregue un cheque si el índice es la raíz e infla una vista diferente. Dado que el encabezado es el único que es diferente que todavía se aprovechan de todas las otras filas que se reutilizan. Incluso puede pre-inflar y almacenar el encabezado y reutilizarlo para deshacerse completamente de la inflación.

Sólo usa un ListView!

Es el más fácil de configurar y más fácil de mantener. Defina un diseño XML para la Lista-Fila y un diseño XML para la Vista que contiene toda la Lista. El ListAdapter hace el resto para usted.

Sólo cree un:

 List<HashMap<String, String>> services = new ArrayList<HashMap<String, String>>(); 

… y recorra sus datos para agregar tantos elementos como desee al mapa. A continuación, establezca este mapa en su ListAdapter. Ya sea 10 elementos o 100 elementos, el ListAdapter creará una lista con muchos elementos.

Ejemplo:

  public void updateProductList(String searchTerm) { createOrOpenDB(this); Cursor cursor = (searchTerm!=null)? dbAdapter.fetchWhere(TBL_NAME, KEY_NAME+" LIKE '%"+searchTerm+"%'") : dbAdapter.fetchAll(TBL_NAME); int rows = cursor.getCount(); if (rows<=0) return; services.clear(); //clear current list for (int i=0; i<rows; i++) { HashMap<String, String> map = new HashMap<String, String>(); cursor.moveToPosition(i); map.put(KEY_NAME, "" + cursor.getString(cursor.getColumnIndex(KEY_NAME))); map.put(KEY_DESC, "" + cursor.getString(cursor.getColumnIndex(KEY_DESC))); map.put(KEY_COST, "" + cursor.getDouble(cursor.getColumnIndex(KEY_COST))); services.add(map); } cursor.close(); closeDB(); ListAdapter adapter = new SimpleAdapter(this, services, R.layout.products_view_row, new String[] {KEY_NAME, KEY_DESC, KEY_COST}, new int[] {R.id.listViewText1, R.id.listViewText2, R.id.listViewText3}); setListAdapter(adapter); } 
  • Diseño de Android con visibilidad GONE
  • Fragmentos y problemas con la pantalla giratoria
  • Uso de Javascript en la vista web
  • Actualizar el menú NavigationView después de cambiar la configuración regional
  • ¿Cómo puedo hacer que `View` llene un` RelativeLayout`?
  • Cómo configurar el color de fondo de una vista
  • Iterar a través de vistas en un diseño y cambiar la tipografía
  • Convertir vista a mapa de bits en Android
  • Android SurfaceView no muestra onDraw
  • Cómo traer una vista al frente sin llamar bringToFront ()?
  • WebView no se dibuja, WARN / webcore (5336): No se puede obtener la viewWidth después del primer diseño
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.