Tengo un GridView
para mostrar algunos iconos.En el adaptador gridview, getView (position == 0) se invocó demasiadas veces para medir el diseño cuando setImageBitmap() en un cargador
Antes de haber leído esta Displaying Bitmaps Efficiently desde el sitio de desarrolladores de Android, que estaba decodificación de mapa de bits de ruta local directamente en getView()
del adaptador, como esto:
public View getView(int position, View convertView, ViewGroup parent) {
...
ImageView icon = ...... (from getTag() of convertView)
icon.setImageBitmap(BitmapUtil.decode(iconPath));
...
}
esta manera funciona bien de todos modos, lo llamé [Modo Directo ], el registro de salida para getView()
método debe ser:
getView(0) // measure kid's layout.
getView(0)
getView(1)
getView(2)
...
getView(n) // when scrolling gridview.
getView(n+1)
...
getView(n+3) // scrolling again.
getView(n+4)
...
entonces yo estoy tratando de cambiar el código para [Modo cargador] mencionado en el artículo Displaying Bitmaps Efficiently, de la siguiente manera:
public View getView(int position, View convertView, ViewGroup parent) {
...
ImageView icon = ...... (from getTag() of convertView)
loadIcon(icon, iconPath);
...
}
en loadIcon()
:
...
final CacheImageLoader loader = new CacheImageLoader(getActivity(), imageView, imageUrl, savePath);
final AsyncDrawable asyncDrawable = new AsyncDrawable(getResources(), placeHolderBitmap, loader);
imageView.setImageDrawable(asyncDrawable);
en oyente de bandeja de carga:
@Override
public void onLoadComplete(Loader<Bitmap> arg0, Bitmap arg1) {
...
ImageView imageView = imageViewReference.get();
if (result != null && imageView != null) {
imageView.setImageBitmap(result);
}
}
Básicamente, es el mismo que el código de la formación, en realidad, de esta manera funciona bien también. Sin embargo, encontré algo diferente, en este modo el método getView()
en el adaptador se invocaba demasiadas veces, sin embargo, estas llamadas repetidas a este método siempre con el parámetro "posición" == 0, significa algo invocar g etView(0, X, X)
repetidamente.
getView(0) // measure kid's layout.
getView(0)
getView(1)
getView(2)
...
getView(0) // loader completed then imageView.setImageBitmap(result);
getView(0) // same as above
getView(0)
getView(0)
...
getView(n) // when scrolling gridview.
getView(n+1)
getView(n+2)
getView(0) // loader completed then imageView.setImageBitmap(result);
getView(0) // same as above
getView(0)
...
getView(n+3) // scrolling again.
getView(n+4)
getView(0) // loader completed then imageView.setImageBitmap(result);
getView(0) // same as above
getView(0)
no es bueno porque estoy utilizando un cargador en getView()
. He comprobado el código fuente y se encontró que son llamados originalmente por imageView.setImageBitmap(result)
en el método de cargador de onLoadComplete
, y en ImageView
:
/**
* Sets a drawable as the content of this ImageView.
*
* @param drawable The drawable to set
*/
public void setImageDrawable(Drawable drawable) {
...
int oldWidth = mDrawableWidth;
int oldHeight = mDrawableHeight;
updateDrawable(drawable);
if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
requestLayout();
}
invalidate();
}
}
aquí, requestLayout()
es el método de vista y siempre se ejecuta en cualquiera [Modo Directo] o [Modo cargador], en View.class:
public void requestLayout() {
mPrivateFlags |= FORCE_LAYOUT;
mPrivateFlags |= INVALIDATED;
if (mLayoutParams != null) {
mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection());
}
if (mParent != null && !mParent.isLayoutRequested()) {
mParent.requestLayout();
}
}
sin embargo, la diferencia es: en [Modo directo], el mParent.requestLayout()
se invoca una vez, pero en [Modo cargador], cada momento en el que yo llamo imageView.setImageBitmap(result);
, la mParent.requestLayout()
será invocado así, significa mParent.isLayoutRequested()
retorno false
y mParent.requestLayout();
hará que el diseño de su niño GridView
medida llamando obtainView()
al primer niño y luego causar getView(0, X, X)
:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
...
mItemCount = mAdapter == null ? 0 : mAdapter.getCount();
final int count = mItemCount;
if (count > 0) {
final View child = obtainView(0, mIsScrap);
...
Por lo tanto, mi pregunta es: ¿por qué mParent.isLayoutRequested()
devuelve false
si estoy usando [modo de cargador]? o es solo un caso normal?
Por lo que sé que es normal, Android puede llamar a cualquier método de su adaptador en cualquier momento y el tiempo que quiera. Incluso varía de una versión a otra. Nunca asumas nada al respecto. 'GridView' es similar a' ListView' así que echa un vistazo a esta gran charla http://www.youtube.com/watch?v=wDBM6wVEO70. A menos que obtenga un error de bloqueo o de memoria baja, no se preocupe y deje que invoque sus métodos. Y sí, en [modo cargador], Android actualizará GUI más adelante cada vez que se llame a OnLoadFinish(). –
Marca "Configuración> Opciones de desarrollador> Mostrar actualizaciones de diseño" y ejecuta tu aplicación. Si la GUI se soluciona cuando todos sus cargadores están terminados, entonces está listo para continuar. –
¿Encontraste una forma de evitar esto? Yo también entiendo esto. – Matthias