我有一个带有自定义BaseAdapter的GridView。在每个单元格中,我(或用户)可以在3个布局(小,中,大)之间选择(通过按钮)来膨胀。如果我选择小,每个单元格的布局都很小:
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
if(convertView == null) {
View temporaryView = myInflater.inflate(R.layout.activity_dialog_box, (ViewGroup) myDialogBox.getWindow().getDecorView().findViewById(android.R.id.content));
Button scaleButton = (Button) temporaryView.findViewById(R.id.dialog_button_scale);
switch (scaleButton.getText().toString()) {
case "small":
Log.e("small","true");
convertView = myInflater.inflate(R.layout.customadapter_view_layout_small, parent, false);
myImg = (ImageView) convertView.findViewById(R.id.imageview_layout_normal_portrait_sizesmall);
myLabelTextView = (TextView) convertView.findViewById(R.id.textview_label_layout_normal_portrait_sizesmall);
myABCTextView = (TextView) convertView.findViewById(R.id.textview_abc_layout_normal_portrait_sizesmall);
break;
case "medium":
Log.e("medium","true");
convertView = myInflater.inflate(R.layout.customadapter_view_layout_medium, parent, false);
myImg = (ImageView) convertView.findViewById(R.id.imageview_layout_normal_portrait_sizemedium);
myLabelTextView = (TextView) convertView.findViewById(R.id.textview_label_layout_normal_portrait_sizemedium);
myABCTextView = (TextView) convertView.findViewById(R.id.textview_abc_layout_normal_portrait_sizemedium);
break;
case "large":
Log.e("large","true");
convertView = myInflater.inflate(R.layout.customadapter_view_layout_large, parent, false);
myImg = (ImageView) convertView.findViewById(R.id.imageview_layout_normal_portrait_sizelarge);
myLabelTextView = (TextView) convertView.findViewById(R.id.textview_label_layout_normal_portrait_sizelarge);
myABCTextView = (TextView) convertView.findViewById(R.id.textview_abc_layout_normal_portrait_sizelarge);
break;
default:
break;
}
convertView.setTag(new Holder(myImg, myLabelTextView, myABCTextView));
在Startup中,对于适合屏幕的每个Cell,convertView为null。所以Switch案例和布局的膨胀以及ImagView和两个TextView的初始化经常发生。对于这种情况,假设用户选择了小:
switch (scaleButton.getText().toString()) {
case "small":
Log.e("small","true");
convertView = myInflater.inflate(R.layout.customadapter_view_layout_small, parent, false);
myImg = (ImageView) convertView.findViewById(R.id.imageview_layout_normal_portrait_sizesmall);
myLabelTextView = (TextView) convertView.findViewById(R.id.textview_label_layout_normal_portrait_sizesmall);
myABCTextView = (TextView) convertView.findViewById(R.id.textview_abc_layout_normal_portrait_sizesmall);
break;
(对性能不利)。所以我想,为什么不在单独的线程中为特定的布局大小设置rootView:
private View inflateLayout() {
View myTestView = null;
switch (scaleButtonText) {
case "small":
myTestView = myInflater.inflate(R.layout.customadapter_view_layout_small, (ViewGroup) gv, false);
break;
case "medium":
myTestView = myInflater.inflate(R.layout.customadapter_view_layout_medium, (ViewGroup) gv, false);
break;
case "large":
myTestView = myInflater.inflate(R.layout.customadapter_view_layout_large, (ViewGroup) gv, false);
break;
default:
break;
}
return myTestView;
}
gv是我的GridView。并将其交给适配器:
myCustomAdapter = new NewCustomAdapter(myActivityContext, myTestView);
稍后,只需在getView方法中将convertView设置为myTestView:
case "small":
Log.e("small","true");
convertView = myTestView;
myImg = (ImageView) convertView.findViewById(R.id.imageview_layout_normal_portrait_sizesmall);
myLabelTextView = (TextView) convertView.findViewById(R.id.textview_label_layout_normal_portrait_sizesmall);
myABCTextView = (TextView) convertView.findViewById(R.id.textview_abc_layout_normal_portrait_sizesmall);
break;
优点是我不必在启动应用程序时一次又一次地对布局进行充气。
问题:我想念一些事情。因为布局没有真正膨胀,所以GridView并不存在或只是处于混乱状态。有人可以解释为什么它不能像这样或我缺少的东西。任何帮助表示赞赏。
答案 0 :(得分:0)
您似乎对适配器的工作方式存在误解。经常调用getView()
。无法确定订单的顺序以及解雇的频率。例如,您可以看到每个位置调用3-4次。这一切都很正常。虽然您可以采取一些措施来降低性能,但在尝试优化时必须小心谨慎。适配器已经被Android高度调整,以尽可能快地执行。尝试通过尝试在单独的线程中膨胀视图来使适配器变得更加智能。不是个好主意。
从适配器的角度来看,您不拥有视图。它确实并且它在幕后使用这些视图做了很多事情......包括性能优化。适配器将自动为您回收视图,以减少您需要充气的次数。 convertView != null
时,您有一个回收的视图。 convertView == null
时,您必须为新视图充气。没有解决这个问题。有时,适配器只是使用getView
创建丢弃视图,其唯一目的是测量ListView需要的大小。
提高性能的一种方法是使用ViewHolder范例,我看到你已经在做了。
如果您在运行时动态更改小型,中型,大型布局,则另一个提示是使用getViewTypeCount()
和getItemViewType()
。内部Android为每种类型保留视图缓存。因此,对于您的情况,它会为您的3个交换机案例中的每一个保留三个缓存池...而不是为所有这些案例保留一个池。
我会说这些话:
View temporaryView = myInflater.inflate(R.layout.activity_dialog_box, (ViewGroup) myDialogBox.getWindow().getDecorView().findViewById(android.R.id.content));
Button scaleButton = (Button) temporaryView.findViewById(R.id.dialog_button_scale);
令人困惑。要膨胀然后搜索视图,只知道要膨胀的视图是一个可以优化的地方。您应该在getView
方法之外确定此信息,并将适当的值传递给适配器,以便确定要遵循的切换案例。
我不确定您的getView
还有什么问题,但根据您发布的内容,您不应该看到任何会影响用户体验的效果。如果您有时间,我强烈建议您观看Google IO谈话" The World of ListView"。它是一个很棒的视频,深入探讨了ListView和适配器的工作方式,你应该做什么和不该做什么,以及人们常见的陷阱。