ImageView 引用和派生的奇怪行为 class
Strange behavior with ImageView reference and derived class
我在 Android Studio 中基于 ConstraintLayout 创建了一些自定义组件。首先,我创建了名为 MyButton 的基础抽象 class,我在其中做一些基本的事情(例如获取对我的组件的引用)。接下来,我创建了派生的 class,称为 MySpecialButton,它扩展了 MyButton,但是当我将 onClickListener 附加到我的 Button 时,我有奇怪的行为,这是我的自定义组件的一部分,并调用修改仅存在于中的元素(参考)的方法来自 onClickListener 的 MySpecialButton。
在目前的代码中,当我尝试从 onClickListener 调用 setImage()
时,结果为日志:E/NULL: ImageView reference is null!
,这意味着从 onClickListener 的角度来看,引用 vImageViev
为空,但是它是在 inflateView
调用中初始化的。但是当我在 inflateView(R.layout.my_special_button)
之后不是从 onClickListener 而是直接从 init()
方法调用 setImage()
时,一切正常。
此外,当我将 protected ImageView vImageView = null;
声明从 MySpecialButton 移动到 MyButton 时,一切正常。
这是我的 MyButton class:
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 class:
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()
?
那是因为 setOnClickListenter 是为基础 class(即 ConstraintLayout)调用的,因为您没有在子 class 中覆盖它无法访问 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);
}
}
我认为您在构造函数中进行了错误的超级调用:
这个
public MySpecialButton(Context context, AttributeSet attr)
{
this(context);
}
应该是:
public MySpecialButton(Context context, AttributeSet attr)
{
super(context, attr);
}
另一个相同 class。并将您的自定义 init 移动到您从每个构造函数调用的不同函数中。
我在 Android Studio 中基于 ConstraintLayout 创建了一些自定义组件。首先,我创建了名为 MyButton 的基础抽象 class,我在其中做一些基本的事情(例如获取对我的组件的引用)。接下来,我创建了派生的 class,称为 MySpecialButton,它扩展了 MyButton,但是当我将 onClickListener 附加到我的 Button 时,我有奇怪的行为,这是我的自定义组件的一部分,并调用修改仅存在于中的元素(参考)的方法来自 onClickListener 的 MySpecialButton。
在目前的代码中,当我尝试从 onClickListener 调用 setImage()
时,结果为日志:E/NULL: ImageView reference is null!
,这意味着从 onClickListener 的角度来看,引用 vImageViev
为空,但是它是在 inflateView
调用中初始化的。但是当我在 inflateView(R.layout.my_special_button)
之后不是从 onClickListener 而是直接从 init()
方法调用 setImage()
时,一切正常。
此外,当我将 protected ImageView vImageView = null;
声明从 MySpecialButton 移动到 MyButton 时,一切正常。
这是我的 MyButton class:
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 class:
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()
?
那是因为 setOnClickListenter 是为基础 class(即 ConstraintLayout)调用的,因为您没有在子 class 中覆盖它无法访问 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);
}
}
我认为您在构造函数中进行了错误的超级调用:
这个
public MySpecialButton(Context context, AttributeSet attr)
{
this(context);
}
应该是:
public MySpecialButton(Context context, AttributeSet attr)
{
super(context, attr);
}
另一个相同 class。并将您的自定义 init 移动到您从每个构造函数调用的不同函数中。