Im gridview-adapter, getView(position == 0) aufgerufen wurde zu oft zu Messen layout, wenn setImageBitmap() in a loader
Ich habe eine GridView
für das zeigen von einigen Symbolen.
BEVOR ich gelesen hatte das Anzeige Von Bitmaps Effizient aus dem Android-developer-Website, war ich Decodierung bitmap aus lokalen Pfad direkt in getView()
adapter, wie diesen :
public View getView(int position, View convertView, ViewGroup parent) {
...
ImageView icon = ...... (from getTag() of convertView)
icon.setImageBitmap(BitmapUtil.decode(iconPath));
...
}
dieser Weg funktioniert gut, wie auch immer, ich nannte es [Direct Mode] die log-Ausgabe für getView()
Methode :
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)
...
dann bin ich versucht den code zu ändern, um [Loader-Modus] im Artikel erwähnt Anzeige Von Bitmaps Effizient, wie folgt :
public View getView(int position, View convertView, ViewGroup parent) {
...
ImageView icon = ...... (from getTag() of convertView)
loadIcon(icon, iconPath);
...
}
in loadIcon()
:
...
final CacheImageLoader loader = new CacheImageLoader(getActivity(), imageView, imageUrl, savePath);
final AsyncDrawable asyncDrawable = new AsyncDrawable(getResources(), placeHolderBitmap, loader);
imageView.setImageDrawable(asyncDrawable);
Loader in den Hörer :
@Override
public void onLoadComplete(Loader<Bitmap> arg0, Bitmap arg1) {
...
ImageView imageView = imageViewReference.get();
if (result != null && imageView != null) {
imageView.setImageBitmap(result);
}
}
Im Grunde ist es dasselbe wie die Ausbildung-code, tatsächlich, auf diese Weise funktioniert auch gut. Allerdings fand ich etwas anderes, in diesem Modus die getView()
Methode in-adapter aufgerufen wurde zu viele Male, aber diese wiederholten Aufruf dieser Methode immer mit "position" - parameter == 0, bedeutet es etwas invoke getView(0, X, X)
wiederholt.
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)
Es ist nicht gut, weil ich bin mit einem loader in getView()
. Ich habe den source-code und fand Sie ursprünglich genannt imageView.setImageBitmap(result)
im loader onLoadComplete
Methode, und in 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();
}
}
hier, requestLayout()
ist View Methode und führt immer entweder [Direct-Modus] oder [- Loader-Modus], in View.class :
public void requestLayout() {
mPrivateFlags |= FORCE_LAYOUT;
mPrivateFlags |= INVALIDATED;
if (mLayoutParams != null) {
mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection());
}
if (mParent != null && !mParent.isLayoutRequested()) {
mParent.requestLayout();
}
}
aber der Unterschied ist: in [Direct-Modus], die mParent.requestLayout()
wird einmal aufgerufen, aber in [Loader-Modus], jedes mal, wenn ich rufe imageView.setImageBitmap(result);
, die mParent.requestLayout()
aufgerufen wird, es bedeutet mParent.isLayoutRequested()
zurück false
, und mParent.requestLayout();
verursachen die GridView
Messen Ihre kid ' s layout durch den Aufruf obtainView()
zum ersten Kind und dann verursachen 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);
...
So, meine Frage ist: warum mParent.isLayoutRequested()
zurück false
wenn ich mit [loader-Modus]? oder ist es nur ein normaler Fall ?
- Soweit ich weiß ist es normal, Android kann jede Methode aufrufen des Adapters jederzeit und so oft Sie es mag. Es auch variiert von version zu version. Nie davon ausgehen, nichts über es.
GridView
ist ähnlichListView
so überprüfen Sie heraus dieses große reden youtube.com/watch?v=wDBM6wVEO70. Es sei denn, Sie sind immer einige Absturz oder memory low Fehler, Mach dir keine Gedanken und lass Sie rufen Ihre Methoden. Und ja, in [- loader-Modus] android wird aktualisiert-GUI später, wenn onLoadFinish() aufgerufen wird. - Überprüfen Sie "Einstellungen>die Entwickler-Optionen" > "Show Layout Updates" und starten Sie Ihre app. Wenn GUI ist entschieden, wenn Ihr alle die Lader fertig sind, dann sind Sie gut zu gehen.
- Hast du eine Möglichkeit, um dieses? Bekomme ich diese auch.
- möglich, Duplikat der benutzerdefinierte listview-adapter getView-Methode wird mehrfach aufgerufen, und in keine kohärente bestellen
Du musst angemeldet sein, um einen Kommentar abzugeben.
isLayoutRequested
ist nur da, um Ihnen zu sagen, wenn ein layout ist bereits anhängig sind, dieseView
. Das ist, nachrequestLayout
genannt wird,isLayoutRequested
true zurückgeben, bis der nächste Layoutphase abgeschlossen. Der einzige Grund für diese check-inrequestLayout
ist zu vermeiden, dass immer wieder ruftrequestLayout
auf die Eltern, wenn es um zu tun, das layout sowieso.isLayoutRequested
ist ein red herring hier: es ist nicht die Ursache vononMeasure
wird immer wieder aufgerufen.Das root-problem ist, dass
ImageView
fordert ein neues layout, wenn Sie ändern Ihre drawable. Dies ist aus zwei Gründen notwendig:-adjustViewBounds
eingestellt ist. Dies könnte wiederum Auswirkungen auf die Größen der anderen Ansichten, je nach dem layout: dieImageView
nicht selbst über genügend Informationen, um wissen.ImageView.onMeasure
ist verantwortlich für die Arbeit heraus, wie weit der drawable muss geändert werden, um fit in dieImageView
's Grenzen, nach der scale-Modus. Wenn die neue drawable nicht die gleiche Größe wie die alten drawable, dieImageView
muss gemessen werden erneut berechnen Sie die erforderliche Skalierung.Können Sie nur beheben das problem, dass zu viele Lader, indem Sie einen lokalen cache
Bitmap
s zurück durch den Lader. Die Caches haben alleBitmap
s, wenn Sie wissen, es gibt nicht so viele, oder nur die n zuletzt verwendeten. In IhremgetView
, prüfen Sie zunächst, ob dieBitmap
für das Element existiert in den cache, und wenn ja, kehren Sie einImageView
bereits festgelegt, dassBitmap
. Nur wenn es nicht in den cache tun, müssen Sie eine loader.Vorsichtig sein: wenn die zugrunde liegenden Daten ändern können, müssen Sie jetzt sicherstellen, um den cache ungültig, zur gleichen Zeit wie der Aufruf von
invalidate
auf dieGridView
oder Benachrichtigung durchContentResolver
. Ich habe einige homebrew-code zu erreichen, das in meiner app, und es funktioniert gut für mich, aber die guten Leute von Square haben eine open-source-Bibliothek namens Picasso zu tun, all die harte Arbeit für Sie, wenn Sie bevorzugen.Dies ist normal Verhaltens -, android nennen kann getView für dieselbe position mehrere Zeit. Es ist auf Entwickler, um die get/set-Miniatur in getView nur wenn erforderlich (D. H. Wenn die Miniaturansicht nicht gesetzt wurde Oder thumbnail-Pfad ändert). In anderen Fällen, nur zurück, convertView, die wir als parameter in getView.
Ich hatte das gleiche problem. Grid ist immer die Messung von Ihrem ersten Kind, auch wenn ich mich in 30 position.
Ich nur zu umgehen das ganze getView-code, indem diese check-in getView top:
Diese nicht aufhören getView genannt, aber zumindest die Texte, Bilder und layout-änderungen, don' t run.
versuchen, passen Sie Ihre xml-layout-auf jeder Stelle, die auf die Höhe, weil die android-tun, eine Maßnahme zu ziehen eachtime und neu gezeichnet, die Zelle wieder.
Versuchen, auf listview match_parent und auf die Zelle in Zeile genau Höhe.
tut mir Leid mein schlechtes Englisch.