【问题标题】:Strange behavior with ImageView reference and derived classImageView 引用和派生类的奇怪行为
【发布时间】:2019-12-11 22:57:08
【问题描述】:

我在 Android Studio 中基于 ConstraintLayout 创建了一些自定义组件。首先,我创建了名为 MyButton 的基本抽象类,我在其中做一些基本的事情(例如,获取对我的组件的引用)。接下来,我创建了名为 MySpecialButton 的派生类,它扩展了 MyButton,但是当我将 onClickListener 附加到我的 Button(这是我的自定义组件的一部分)时,我有奇怪的行为,并调用修改仅存在于来自 onClickListener 的 MySpecialButton 中的元素(引用)的方法。

在当前代码中,当我尝试从 onClickListener 调用 setImage() 时,最终会出现日志:E/NULL: ImageView reference is null!,这意味着从 onClickListener 的角度来看,引用 vImageViev 为空,但它在 @987654324 中初始化@ 称呼。但是当我不是从 onClickListener 而是直接从 init() 方法在 inflateView(R.layout.my_special_button) 之后调用 setImage() 时,一切正常。 此外,当我将 protected ImageView vImageView = null; 声明从 MySpecialButton 移动到 MyButton 时,一切正常。

这是我的 MyButton 类:

public abstract class MyButton extends ConstraintLayout
{
    protected Context context = null;

    protected View rootView = null;
    protected Button vButton = null;
    protected Switch vSwitch = null;

    public MyButton(Context context)
    {
        super(context);
        this.context = context;
        init();
    }

    public MyButton(Context context, AttributeSet attrs)
    {
        this(context);
    }

    protected abstract void init();

    protected void inflateView(int res)
    {
        rootView = inflate(context, res, this);

        vButton = (Button)rootView.findViewById(R.id.vButton);
        vSwitch = (Switch)rootView.findViewById(R.id.vSwitch);
    }
}

这是我的 MySpecialButton 类:

public class MySpecialButton extends MyButton
{
    protected ImageView vImageView = null;

    public MySpecialButton(Context context)
    {
        super(context);
    }

    public MySpecialButton(Context context, AttributeSet attr)
    {
        this(context);
    }


    @Override
    protected void inflateView(int res)
    {
        super.inflateView(res);

        vImageView = (ImageView)rootView.findViewById(R.id.vImageView);
    }

    protected void init()
    {
        inflateView(R.layout.my_special_button);

        vButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                setImage();
            }
        });
    }

    protected void setImage()
    {
        if(vImageView == null)
            Log.e("NULL", "ImageView reference is null!");
        else
            vImageView.setImageResource(R.drawable.ic_window);
    }
}

发生了什么事?我应该怎么做才能在没有空引用的情况下从 onClickListener 调用 setImage()

【问题讨论】:

    标签: java android derived-class


    【解决方案1】:

    我认为你在构造函数中做了错误的超级调用:

    这个

    public MySpecialButton(Context context, AttributeSet attr)
    {
        this(context);
    }
    

    应该是:

    public MySpecialButton(Context context, AttributeSet attr)
    {
        super(context, attr);
    }
    

    其他类也是如此。并将您的自定义初始化移动到您从每个构造函数调用的不同函数中。

    【讨论】:

    • 谢谢!我将 init() 调用从 MyButton 移动到 MySpecialButton 构造函数,它开始工作。我不知道为什么,但这确实有效。
    【解决方案2】:

    这是因为 setOnClickLisnter 是为基类(即 ConstraintLayout)调用的,因为您没有在无法访问 ImageView 的子类中覆盖它。

    试试这个:

    public abstract class MyButton extends ConstraintLayout
    {
        protected Context context = null;
    
        protected View rootView = null;
        protected Button vButton = null;
        protected Switch vSwitch = null;
    
        //...
    
        @Override
        public void setOnClickListener(@Nullable OnClickListener l) {
            vButton.setOnClickLisnter(l);
        }
    }
    

    【讨论】:

    • 不幸的是,它对我不起作用。但是,如果我理解正确,则不会为 ConstraintLayout 类调用 setOnClickListener,而是为 Button 类调用 setOnClickListener。如果你是对的,为什么将 vImageView 声明从 MySpecialButton 移动到 MyButton 可以解决问题,即使 vImageView 仍然无法从 ConstraintLayout 类访问?
    猜你喜欢
    • 2012-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 2016-04-26
    • 2015-05-16
    相关资源
    最近更新 更多