Android:重用 gridview 中的嵌入视图 [已发布解决方案]
我正在尝试重用其中包含图像和文本视图的框架布局,但我认为我做得不对。代码有效并且显示正确,但性能非常差,我相信这是因为每次适配器返回到项目位置时我都会创建一个新的 ImageView 和 TextView 。
有人可以告诉我如何重用嵌入的 ImageView (称为 i)和 TextView (称为 t)而不创建新对象吗?我对 Java 非常陌生,这是我构建 Android 应用程序的尝试。
public View getView(int position, View convertView, ViewGroup parent) {
FrameLayout F;
FrameLayout ImageBorder;
FrameLayout TextBG;
ImageView i;
TextView t;
if(convertView == null) {
F = new FrameLayout(mContext);
} else {
F = (FrameLayout) convertView;
}
ImageBorder = new FrameLayout(F.getContext());
FrameLayout.LayoutParams params1 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT,300,Gravity.BOTTOM);
ImageBorder.setLayoutParams(params1);
i = new ImageView(F.getContext());
TextBG = new FrameLayout(F.getContext());
t = new TextView(F.getContext());
F.setBackgroundColor(Color.BLACK);
ImageBorder.setPadding(2, 2, 2, 2);
ImageBorder.setBackgroundColor(Color.BLACK);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT,40,Gravity.BOTTOM);
TextBG.setLayoutParams(params);
TextBG.setBackgroundColor(Color.BLACK);
TextBG.setAlpha(.6f);
t.setLayoutParams(params);
t.setGravity(Gravity.CENTER_VERTICAL);
String pathToPhoto = FileList.get(position).toString();
String fileDescription = pathToPhoto.replaceAll("/mnt/external1/PaliPhotography/","");
fileDescription = fileDescription.replaceAll(".jpg","");
fileDescription = fileDescription.toUpperCase();
Bitmap bm = Cache.getCacheFile("thumb",pathToPhoto);
if (bm == null) {
ImageDownloader downloader = new ImageDownloader(i);
downloader.execute("thumb", pathToPhoto, "400", "400");
} else {
i.setImageBitmap(bm);
i.setScaleType(ImageView.ScaleType.CENTER_CROP);
t.setTextAppearance(getApplicationContext(), android.R.style.TextAppearance_Large);
t.setText(" " + fileDescription);
}
ImageBorder.addView(i);
ImageBorder.addView(TextBG);
ImageBorder.addView(t);
F.addView(ImageBorder);
return F;
}
}
先感谢您!
[编辑]
---------------------------- 解决方案 --------- --------------------------------------------------------
这里是我根据下面的反馈实施的解决方案!谢谢你!
public View getView(int position, View convertView, ViewGroup parent) {
View ReturnThisView;
ViewHolder holder;
LayoutInflater inflater;
holder = new ViewHolder();
if(convertView == null) {
inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ReturnThisView = inflater.inflate(R.layout.imagecell, null);
ReturnThisView.setTag(holder);
} else {
ReturnThisView = convertView;
}
holder.TextDescription = (TextView) ReturnThisView.findViewById(R.id.PhotoDesc);
holder.ImageThumbnail = (ImageView) ReturnThisView.findViewById(R.id.Thumbnail);
String pathToPhoto = FileList.get(position).toString();
String fileDescription = pathToPhoto.replaceAll("/mnt/external1/PaliPhotography/","");
fileDescription = fileDescription.replaceAll(".jpg","");
fileDescription = fileDescription.toUpperCase();
Bitmap bm = Cache.getCacheFile("thumb",pathToPhoto);
if (bm == null) {
ImageDownloader downloader = new ImageDownloader(holder.ImageThumbnail);
downloader.execute("thumb", pathToPhoto, "400", "400");
} else {
holder.ImageThumbnail.setImageBitmap(bm);
holder.ImageThumbnail.setScaleType(ImageView.ScaleType.CENTER_CROP);
holder.TextDescription.setTextAppearance(getApplicationContext(), android.R.style.TextAppearance_Large);
holder.TextDescription.setText(" " + fileDescription);
}
return ReturnThisView;
}
}
static class ViewHolder {
TextView TextDescription;
ImageView ImageThumbnail;
}
I am trying to reuse a framelayout that has an image and textview inside it but I don't think I am doing this right. The code works and the display is right but the performance is very poor and I believe it is because I creating a new ImageView and TextView every time the adapters goes back to the item position.
Can someone tell me how to reuse the embedded ImageView (called i) and TextView (called t) without creating new objects? I am very new to Java and this is my attempt at building a Android application.
public View getView(int position, View convertView, ViewGroup parent) {
FrameLayout F;
FrameLayout ImageBorder;
FrameLayout TextBG;
ImageView i;
TextView t;
if(convertView == null) {
F = new FrameLayout(mContext);
} else {
F = (FrameLayout) convertView;
}
ImageBorder = new FrameLayout(F.getContext());
FrameLayout.LayoutParams params1 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT,300,Gravity.BOTTOM);
ImageBorder.setLayoutParams(params1);
i = new ImageView(F.getContext());
TextBG = new FrameLayout(F.getContext());
t = new TextView(F.getContext());
F.setBackgroundColor(Color.BLACK);
ImageBorder.setPadding(2, 2, 2, 2);
ImageBorder.setBackgroundColor(Color.BLACK);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT,40,Gravity.BOTTOM);
TextBG.setLayoutParams(params);
TextBG.setBackgroundColor(Color.BLACK);
TextBG.setAlpha(.6f);
t.setLayoutParams(params);
t.setGravity(Gravity.CENTER_VERTICAL);
String pathToPhoto = FileList.get(position).toString();
String fileDescription = pathToPhoto.replaceAll("/mnt/external1/PaliPhotography/","");
fileDescription = fileDescription.replaceAll(".jpg","");
fileDescription = fileDescription.toUpperCase();
Bitmap bm = Cache.getCacheFile("thumb",pathToPhoto);
if (bm == null) {
ImageDownloader downloader = new ImageDownloader(i);
downloader.execute("thumb", pathToPhoto, "400", "400");
} else {
i.setImageBitmap(bm);
i.setScaleType(ImageView.ScaleType.CENTER_CROP);
t.setTextAppearance(getApplicationContext(), android.R.style.TextAppearance_Large);
t.setText(" " + fileDescription);
}
ImageBorder.addView(i);
ImageBorder.addView(TextBG);
ImageBorder.addView(t);
F.addView(ImageBorder);
return F;
}
}
Thank you in advance!
[EDIT]
--------------------------- SOLUTION -----------------------------------------------------
Here is solution that I implemented based on the feedback below! Thank you!
public View getView(int position, View convertView, ViewGroup parent) {
View ReturnThisView;
ViewHolder holder;
LayoutInflater inflater;
holder = new ViewHolder();
if(convertView == null) {
inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ReturnThisView = inflater.inflate(R.layout.imagecell, null);
ReturnThisView.setTag(holder);
} else {
ReturnThisView = convertView;
}
holder.TextDescription = (TextView) ReturnThisView.findViewById(R.id.PhotoDesc);
holder.ImageThumbnail = (ImageView) ReturnThisView.findViewById(R.id.Thumbnail);
String pathToPhoto = FileList.get(position).toString();
String fileDescription = pathToPhoto.replaceAll("/mnt/external1/PaliPhotography/","");
fileDescription = fileDescription.replaceAll(".jpg","");
fileDescription = fileDescription.toUpperCase();
Bitmap bm = Cache.getCacheFile("thumb",pathToPhoto);
if (bm == null) {
ImageDownloader downloader = new ImageDownloader(holder.ImageThumbnail);
downloader.execute("thumb", pathToPhoto, "400", "400");
} else {
holder.ImageThumbnail.setImageBitmap(bm);
holder.ImageThumbnail.setScaleType(ImageView.ScaleType.CENTER_CROP);
holder.TextDescription.setTextAppearance(getApplicationContext(), android.R.style.TextAppearance_Large);
holder.TextDescription.setText(" " + fileDescription);
}
return ReturnThisView;
}
}
static class ViewHolder {
TextView TextDescription;
ImageView ImageThumbnail;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
convertView == null
使用 inflater 膨胀新行convertView.setTag(holder)
holder = ConvertView.getTag()
找到 Holder 对象,holder.txt.setText("Foo")
可以说,即使对于您的代码,您也可以执行一次视图初始化和布局并使用 Holder模式以避免元素重新初始化,但我认为 XML 会给你更好的体验
convertView == null
inflate new row by using inflaterconvertView.setTag(holder)
holder = convertView.getTag()
holder.txt.setText("Foo")
Arguably even for your code you can do view initialization and layout once and use Holder pattern to avoid re-initialization of the elements but I think XML will give you better experience
您提供的解决方案不准确。 ViewHolder 主要用于避免膨胀视图并多次调用 findViewById()。
在您的代码中,
您不应该每次都创建一个新的持有者对象!相反,您应该仅当您的convertView = null 时创建一个新的viewholder,然后将其保存在ReturnThisView 标记中。如果convertView不为null,那么您应该加载之前保存的viewholder。
您避免了视图膨胀,做得很好 (y),但您仍然使用 findViewById()。仅当 ConvertView = null 且您正在初始化视图持有者中的视图时才使用 findViewById() 。如果convertView不为null,那么只需使用您加载的viewHolder对象中保存的视图。
这是一个例子:
}
我从这个网站。
The solution you provided is not accurate. The ViewHolder is mainly used to avoid inflating the view and calling findViewById() more than once.
In your code,
You should not create a new holder object every time! Instead, you should create a new viewholder only when your convertView = null, then save it in the ReturnThisView tag. If the convertView is not null, then you should load that viewholder you saved before.
You avoided inflating the view, so well done (y), but you still use findViewById(). Only use findViewById() when convertView = null and you are initializing the views in the view holder. If convertView is not null, then just use the saved views in the viewHolder object you loaded.
Here is an example:
}
I learned it from this site.