RecyclerView onCreateViewHolder llamado excesivamente cuando se desplaza rápidamente con DPAD
Estoy desarrollando en Amazon Fire TV.
Debido a que es una aplicación de TV (sin toque), necesito focusables dentro de la disposición de la fila para poder navegar alrededor.
- ¿Cómo puedo pasar una función como un parámetro a otra función en android?
- Colocación de varias tablas / columnas en un archivo CSV
- Realm.io no puede conseguir ejemplos para trabajar
- Obtener bandera emoji por código de país
- R.string.XXX devuelve un int de strings.xml cuando necesito una String
Tengo un Recyclerview
muy simple con la imagen, el texto, y un focusable. Cuando presiono hacia arriba o hacia abajo, todo se desplaza y las cosas correctamente, pero me di cuenta de que cuando navego más rápido de desplazamiento puede mantener, crea nuevos espectadores (fuera de pantalla) y retrasa la interfaz de usuario.
He creado una actividad con números de Creación en él. Cuando me desplazo lentamente, la mayor creación # es 10. Pero cuando me desplazo rápido, consigo tarjetas con la creación número 60 en un segundo. Esto causa un retraso enorme y la aplicación deja caer una gran cantidad de marcos. ¿Es mi enfoque totalmente equivocado?
Utilice el siguiente código para probar esto.
/** * Created by sylversphere on 15-04-15. */ public class LandfillActivity extends Activity{ private Context context; private static int ticketNumber; private static int getTicket(){ ticketNumber ++; return ticketNumber; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); context = this; setContentView(R.layout.landfill_activity); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView); GridLayoutManager glm = new GridLayoutManager(context, 2); recyclerView.setLayoutManager(glm); SickAdapter sickAdapter = new SickAdapter(); recyclerView.setAdapter(sickAdapter); } public class SickViewHolder extends RecyclerView.ViewHolder{ TextView ticketDisplayer; public ImageView imageView; public SickViewHolder(View itemView) { super(itemView); ticketDisplayer = (TextView) itemView.findViewById(R.id.ticketDisplayer); imageView = (ImageView) itemView.findViewById(R.id.imageView); itemView.findViewById(R.id.focus_glass).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { context.startActivity(new Intent(context, LouisVuittonActivity.class)); } }); } public void setTicket(int value){ ticketDisplayer.setText(""+value); } } public class SickAdapter extends RecyclerView.Adapter<SickViewHolder>{ @Override public SickViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { SickViewHolder svh = new SickViewHolder(getLayoutInflater().inflate(R.layout.one_row_element, null)); svh.setTicket(getTicket()); return svh; } @Override public void onBindViewHolder(SickViewHolder holder, int position) { String[] image_url_array = getResources().getStringArray(R.array.test_image_urls); Picasso.with(context).load(image_url_array[position % image_url_array.length] ).fit().centerCrop().into(holder.imageView); } @Override public int getItemCount() { return 100000; } } }
One_row_element.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <FrameLayout android:layout_width="match_parent" android:layout_height="200dp" android:orientation="horizontal"> <ImageView android:id="@+id/imageView" android:layout_width="match_parent" android:layout_height="match_parent" android:adjustViewBounds="true" android:scaleType="centerCrop" android:src="@mipmap/sick_view_row_bg" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="left|center_vertical" android:layout_marginLeft="15dp" android:orientation="horizontal"> <TextView android:id="@+id/virusTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Creation #" android:textColor="#fff" android:textSize="40sp" /> <TextView android:id="@+id/ticketDisplayer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="1" android:textColor="#fff" android:textSize="40sp" /> </LinearLayout> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/focus_glass" android:background="@drawable/subtle_focus_glass" android:focusable="true" android:focusableInTouchMode="true"/> </FrameLayout> </FrameLayout>
Test_image_urls.xml (Urls no es propiedad de mí)
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="test_image_urls" formatted="false"> <item>http://farm4.static.flickr.com/3175/2737866473_7958dc8760.jpg</item> <item>http://farm4.static.flickr.com/3276/2875184020_9944005d0d.jpg</item> <item>http://farm3.static.flickr.com/2531/4094333885_e8462a8338.jpg</item> <item>http://farm4.static.flickr.com/3289/2809605169_8efe2b8f27.jpg</item> <item>http://2.bp.blogspot.com/_SrRTF97Kbfo/SUqT9y-qTVI/AAAAAAAABmg/saRXhruwS6M/s400/bARADEI.jpg</item> <item>http://fortunaweb.com.ar/wp-content/uploads/2009/10/Caroline-Atkinson-FMI.jpg</item> <item>http://farm4.static.flickr.com/3488/4051378654_238ca94313.jpg</item> <item>http://farm4.static.flickr.com/3368/3198142470_6eb0be5f32.jpg</item> <item>http://www.powercai.net/Photo/UploadPhotos/200503/20050307172201492.jpg</item> <item>http://www.web07.cn/uploads/Photo/c101122/12Z3Y54RZ-22027.jpg</item> <item>http://www.mitravel.com.tw/html/asia/2011/Palau-4/index_clip_image002_0000.jpg</item> <item>http://news.xinhuanet.com/mil/2007-05/19/xinsrc_36205041914150623191153.jpg</item> <item>http://ib.berkeley.edu/labs/koehl/images/hannah.jpg</item> <item>http://down.tutu001.com/d/file/20110307/ef7937c2b70bfc2da539eea9df_560.jpg</item> <item>http://farm3.static.flickr.com/2278/2300491905_5272f77e56.jpg</item> <item>http://www.pic35.com/uploads/allimg/100526/1-100526224U1.jpg</item> <item>http://img.99118.com/Big2/1024768/20101211/1700013.jpg</item> <item>http://farm1.static.flickr.com/45/139488995_bd06578562.jpg</item> </string-array> </resources>
Enfoque sutil
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_focused="true" android:drawable="@color/glass_focus"/> <item android:drawable="@color/glass_normal"/> </selector>
glass_normal
es #9000
glass_focus
es #0000
- Android AccountManager lanza AuthenticatorException: falla de enlace al agregar cuenta
- Android Studio - con Junit 4.12 "!!! JUnit versión 3.8 o posterior esperado: "
- Convertir RGB a HSV en Android
- Descargar rstp stream en android
- ¿Cómo puedo grabar audio en Android y cambiar el tono?
- Rotar vídeo con mp4parser de acuerdo con la cámara utilizada
- No puede utilizar el método "getString (int resId)" en FragmentPagerAdapter
- Error: Error de ejecución para la tarea ': lib: compileReleaseAidl'. > Ejecutor Singleton no iniciado
Intente aumentar el número máximo de vistas recicladas en la agrupación:
recyclerView.getRecycledViewPool().setMaxRecycledViews(50);
50 es un número arbitrario, puedes probar más o menos y ver qué pasa.
RecyclerView intenta evitar volver a usar las vistas que tienen un estado transitorio , por lo que si las vistas se invalidan rápidamente o se animan, es posible que no se vuelvan a utilizar de inmediato.
Del mismo modo, si tiene muchas vistas más pequeñas, puede terminar con más en la pantalla que el tamaño de grupo predeterminado puede manejar (más común con la cuadrícula como diseños).
Picasso es la celebración de usted, pero la solución sugerida para construir su propio mecanismo no es el camino a seguir.
Picasso se ha quedado atrás en el último año y hoy hay alternativas mucho mejores en forma de Google Glide y Facebook Fresco que específicamente lanzó actualizaciones para trabajar mejor con RecyclerView y han demostrado ser más rápido y más eficiente en la carga, almacenamiento en memoria caché y almacenamiento en muchos Pruebas disponibles en línea tales como:
- http://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en
- https://code.facebook.com/posts/366199913563917/introducing-fresco-a-new-image-library-for-android/
Espero que ayudó. Buena suerte.
Como los comentaristas señalaron las respuestas pendientes de Picasso podría ser la celebración de usted. Si ese es el caso, puede solucionarlo extendiendo ImageView
y reemplazando el siguiente método. Creo que vale la pena intentarlo.
@Override protected void onDetachedFromWindow() { Picasso.with(context).cancelRequest(this); super.onDetachedFromWindow(); }
Actualizar:
Resulta que esta no es la forma correcta, cualquier persona que desee cancelar las solicitudes debe hacerlo en la devolución de llamada onViewRecycled()
como se señala en los comentarios a continuación.
Para cualquiera que esté buscando un hack rápido, haz esto. Esto retrasará la selección hasta que se haya inflado y seleccionado. No sé cómo, pero funciona. Solo devuelve null en onFocusSearchFailed.
/** * Created by sylversphere on 15-04-22. */ public class SomeGridLayoutManager extends GridLayoutManager{ private final Context context; public SomeGridLayoutManager(Context context, int spanCount) { super(context, spanCount); this.context = context; } public SomeGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) { super(context, spanCount, orientation, reverseLayout); this.context = context; } @Override public View onFocusSearchFailed(View focused, int focusDirection, RecyclerView.Recycler recycler, RecyclerView.State state) { return null; } }
- Patrones de uso de la actividad Transición vs Fragmentos dinámicos
- Android Studio gradle – ### – bin.zip vs gradle – ### – todos.zip