【问题标题】:Android custom view event listeners not working properly without static referenceAndroid 自定义视图事件侦听器在没有静态引用的情况下无法正常工作
【发布时间】:2017-06-30 19:01:51
【问题描述】:

我正在 android 中创建一个自定义复合视图,其中包含相对布局中的两个 TextView。有两个类,一个是 BarcodeScannerView,它是复合视图,另一个是使用自定义视图的活动。代码如下。

BarcodeScannerView.java

    public class BarcodeScannerView extends RelativeLayout implements View.OnClickListener {

    private int boxRadius;
    private String boxText;
    private int boxColor, boxEntityColor;
    private TextView entityName;
    private TextView manualEntry;
    private ImageView scannerReadyImv;
    private RelativeLayout scannerBox;
    private OnClickListener listener;
    private ScannerListener scanner;
    private ScannerState state;
   // private static BarcodeScannerView instance;

    public enum ScannerState {
        IDLE, READY, COMPLETE;
    }

    public interface ScannerListener {

        void onClickScannerBox();
        void scannerIdle();
    }

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

    public BarcodeScannerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {

        View.inflate(context, R.layout.activity_barcode_scanner, this);
        setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);

        entityName = (TextView) findViewById(R.id.entityNameTV);
        manualEntry = (TextView) findViewById(R.id.manualEntryTV);
        scannerReadyImv = (ImageView) findViewById(R.id.scannerReadyImv);
        scannerBox = (RelativeLayout) findViewById(R.id.scannerBox);

        manualEntry.setOnClickListener(this);
        scannerBox.setOnClickListener(this);

        // Assign custom attributes
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.barcodeviewer, 0, 0);

        try {

            boxEntityColor = a.getInteger(R.styleable.barcodeviewer_boxEntityColor, 0);
            setBoxEntityColor(boxEntityColor);

        } finally {
            a.recycle();
        }

    }

    // Set custom attributes
    private void setBoxEntityColor(int color) {
        this.entityName.setTextColor(color);
    }

    // Set event handlers
    public void setOnClickListener(OnClickListener listener) {
        this.listener = listener;
    }

    public void setOnScannerListener(ScannerListener scanner) {
        this.scanner = scanner;
    }


    // Setters and getters
    public void setScannerState(ScannerState state) {
        this.state = state;
    }

    public ScannerState getScannerState() {
        return this.state;
    }

    private void setScannerReadyState() {
        scannerBox.setBackgroundResource(R.drawable.bc_active_4);
        scannerReadyImv.setVisibility(View.VISIBLE);
    }

    public void onClick(View v) {

        if (v.getId() == R.id.scannerBox) {
            this.scanner.onClickScannerBox();
            if (this.getScannerState() == ScannerState.IDLE) {
                setScannerReadyState();
            }
        }
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity implements BarcodeScannerView.ScannerListener {

private BarcodeScannerView barcodeScannerView;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);
    /*barcodeScannerView = BarcodeScannerView.instance(MainActivity.this);
    barcodeScannerView.setOnScannerListener(this);*/
    barcodeScannerView = new BarcodeScannerView(this);
    barcodeScannerView.setOnScannerListener(this);
}

@Override
public void onClickScannerBox() {
    scannerIdle();
}

@Override
public void scannerIdle(){
    barcodeScannerView.setScannerState(BarcodeScannerView.ScannerState.IDLE);
}

}

问题是当我调用 BarcodeScannerView 类的 onClick() 方法时,它会给出一个空点异常。

java.lang.NullPointerException:尝试在空对象引用上调用接口方法“void [packagename]$ScannerListener.onClickScannerBox()”

在调试中,我注意到当调用 onClickScannerBox() 时,扫描仪对象被初始化。但是在 BarcodeScannerView 中执行 onClickScannerBox() 之后,扫描仪对象变为空。

根据我的观察,原因是当 onClickScannerBox() 被调用时,一个 BarcodeScannerView 对象实例被初始化,当 onClickScannerBox() 完成并退出该方法时,因为它位于另一个 BarcodeScannerView 对象实例的 onClick() 方法中扫描仪对象为空。

我可以使用静态扫描器对象简单地纠正这个问题。 (这里没有提供代码,因为太长了)我不认为静态引用是解决这个问题的最佳方法。有什么方法可以在不使用任何静态引用的情况下纠正问题?任何建议表示赞赏。

【问题讨论】:

    标签: java android event-handling android-custom-view


    【解决方案1】:

    在您的实现中,您的自定义复合视图有两个实例起作用,一个在布局(活动布局)中,另一个在活动onCreate 方法中显式创建。

    barcodeScannerView = new BarcodeScannerView(this);
    barcodeScannerView.setOnScannerListener(this);
    

    您已将侦听器设置为显式创建的侦听器,该侦听器不知道布局中使用的视图,只是它们是两个实例。您应该使用在 xml 中创建(膨胀)的实例,如下所示。

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);
    
        barcodeScannerView = (BarcodeScannerView) findViewById(R.id.barcode_scanner);
        barcodeScannerView.setOnScannerListener(this);
    }
    

    barcode_scanner 应该是您为活动布局中使用的复合视图指定的 ID。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-31
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 2019-10-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多