自定义preference onBindView易犯的错误

public class PowerInformationPreference extends Preference {

    private TextView firstName;

    public PowerInformationPreference(Context context, AttributeSet attr, int defStyle) {
        super(context, attr, defStyle);
        setLayoutResource(R.layout.layout_power_information);
    }

    @Override
    protected void onBindView(View view) {(1)
        // TODO Auto-generated method stub
        super.onBindView(view);
        firstName = (TextView)view.findViewById(R.id.firstname);(2)
    }

}

上面是我们很常见到的自定义preference的基本形式,我们在onBindView()函数中操作自定义视图,比如上面的代码中我们需要动态的改变firstName这一TextView的text值。

如下,我们提供一个setText()接口,通过这个接口我们可以动态改变TextView的text值。

public void setText(String text){(3)
    firstName.setText(text);//NullPointerException(4)
}

如果我们真的是这样写这个接口的话,会发现一定会出现NullPointerException,调试发现这里的firstName为空。而回到onBindView()中调试分析又会发现,firstName = (TextView)view.find...实际上是会运行的,也就是有这个firstName对象存在。那么唯一的解释就是setText()的调用在onBindView()运行之前,因此我们的疑惑来了,如何确保onBindView()在setText()调用之前运行呢?

事实上,到这里我们如果继续这样分析的话,就会钻入误区,跳出来,从逻辑层面上想想,我们会发现,(1),(2),(4)是对UI的操作,(3)是对数据的操作。这里,(1)(2)和(4)分开了,也就是说,(1)(2)运行的时候不能保证(4)运行;(4)运行的时候不能保证(1)(2)运行,这对UI操作是非常危险的事,很容易就产生了控制正异常。

不仅仅是这里,我们查看Adapter.java的源码,查看有getView(), onCreateView(), onBindView()等类的相关源码,都会发现,凡是涉及到UI操作的一定是放在一起的。


现给出上例的修正方案:

public class PowerInformationPreference extends Preference {

    private TextView firstName;
    private String text;

    public PowerInformationPreference(Context context, AttributeSet attr, int defStyle) {
        super(context, attr, defStyle);
        setLayoutResource(R.layout.layout_power_information);
    }

    @Override
    protected void onBindView(View view) {(1)
        // TODO Auto-generated method stub
        super.onBindView(view);
        firstName = (TextView)view.findViewById(R.id.firstname);(2)
        firstName.setText(text);
    }

public void setText(String text){(3) this.text = text;
notifyChanged();
}
}

这里还需要强调的一点是一定不要忘记notifyChanged()这个函数通知UI更新数据,否则我们会发现通过这个接口设置的数据并没有改变原来的值。这个函数如同View中的invalidate(),虽然数据更新了,但是显示在视图中的数字图像依然没变,因此需要通知UI更新显示。

自定义preference onBindView易犯的错误

上一篇:数据分析相关知识梳理总结


下一篇:教你用PS制作逼真的皱褶纸张文字效果