在BaseAdapter中优化getView

时间:2014-11-26 13:02:57

标签: android gridview baseadapter

我有一个带有自定义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并不存在或只是处于混乱状态。有人可以解释为什么它不能像这样或我缺少的东西。任何帮助表示赞赏。

1 个答案:

答案 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和适配器的工作方式,你应该做什么和不该做什么,以及人们常见的陷阱。