GridView
いくつかのアイコンを表示するためのがあります。
Android開発者サイトからこの「ビットマップの表示」を効率的に読む前にgetView()
、次のように、アダプターのローカルパスから直接ビットマップをデコードしていました。
public View getView(int position, View convertView, ViewGroup parent) {
...
ImageView icon = ...... (from getTag() of convertView)
icon.setImageBitmap(BitmapUtil.decode(iconPath));
...
}
この方法はとにかく正常に機能します。私はそれを[ダイレクトモード]と呼びました。getView()
メソッドの出力ログは次のようになります。
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)
...
次に、次のように、記事「ビットマップを効率的に表示する」で説明されている[ローダーモード]にコードを変更しようとしています。
public View getView(int position, View convertView, ViewGroup parent) {
...
ImageView icon = ...... (from getTag() of convertView)
loadIcon(icon, iconPath);
...
}
でloadIcon()
:
...
final CacheImageLoader loader = new CacheImageLoader(getActivity(), imageView, imageUrl, savePath);
final AsyncDrawable asyncDrawable = new AsyncDrawable(getResources(), placeHolderBitmap, loader);
imageView.setImageDrawable(asyncDrawable);
ローダーのリスナーで:
@Override
public void onLoadComplete(Loader<Bitmap> arg0, Bitmap arg1) {
...
ImageView imageView = imageViewReference.get();
if (result != null && imageView != null) {
imageView.setImageBitmap(result);
}
}
基本的にはトレーニングコードと同じですが、実際にはこの方法でも問題なく機能します。しかし、私は何か違うものを見つけました。このモードではgetView()
、アダプターのメソッドが何度も呼び出されましたが、このメソッドへのこれらの繰り返し呼び出しは常に「position」パラメーター== 0であり、何かがgetView(0, X, X)
を繰り返し呼び出すことを意味します。
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)
でローダーを使用しているので良くありませんgetView()
。ソースコードを確認したところ、元々imageView.setImageBitmap(result)
ローダーの onLoadComplete
メソッドで呼び出されていたことがわかりました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();
}
}
ここでrequestLayout()
は、Viewのメソッドであり、View.classの[DirectMode]または[LoaderMode]のいずれかで常に実行されます。
public void requestLayout() {
mPrivateFlags |= FORCE_LAYOUT;
mPrivateFlags |= INVALIDATED;
if (mLayoutParams != null) {
mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection());
}
if (mParent != null && !mParent.isLayoutRequested()) {
mParent.requestLayout();
}
}
ただし、違いは次のとおりです。[ダイレクトモード]では、 mParent.requestLayout()
は1回呼び出されますが、[ローダーモード]では、呼び出すたびにimageView.setImageBitmap(result);
、 も呼び出されます。これは、リターンをmParent.requestLayout()
意味し、を呼び出すことで子供のレイアウトを測定します。最初の子供にそして次に引き起こす:mParent.isLayoutRequested()
false
mParent.requestLayout();
GridView
obtainView()
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);
...
だから、私の質問は、 [ローダーモード]を使用しているのになぜmParent.isLayoutRequested()
戻るのかということです。false
それとも通常の場合ですか?