簡體   English   中英

如何從java中另一個類的事件偵聽器中檢索值?

[英]How to retrieve the value from the event listener from another class in java?

我有一個程序可以從條形碼掃描儀(使用 jssc 庫)獲取值,它使用事件偵聽器按預期返回值,但我需要從另一個類訪問該值。

我嘗試將 BarcodeScanner 類實例化為 main 方法(ProcessTicket 類)並調用scannerHandler 方法,還調用模型類的 getter 方法來檢索值,但 getter 方法在掃描完成之前運行。 你能幫我實現這個目標嗎?

    public class BarcodeScanner {
            public static Object SerialPortReader;
            static SerialPort serialPort;
         public void scannerHandler() {
                serialPort = new SerialPort("COM4");      
    try{
       serialPort.openPort();//Open serial port
      //Set params. Also set params by this string: 
       serialPort.setParams(9600, 8, 1, 0);
       serialPort.setParams(9600, 8, 1, 0);
       serialPort.writeString(new String(new byte[]{0x02})); //triggers barcode scanner
       serialPort.addEventListener(new SerialPortReader());//Add SerialPortEventListenerS
    } catch (SerialPortException ex) {
                    System.out.println(ex);
                }
            }

        public static class SerialPortReader implements SerialPortEventListener {
                String str;
                String value;

                public void serialEvent(SerialPortEvent event) {
                    if (event.isRXCHAR() && event.getEventValue() > 0) {//If data is available
                        //Check bytes count in the input buffer
                        try {
                            byte[] bytesCont = serialPort.readBytes(14);
                            str = new String(bytesCont);
                            ModelClass modelClass = new ModelClass();
                            modelClass.setBarcodeValue(str);
                        } catch (SerialPortException e) {
                            e.printStackTrace();
                        }
                    }
        }

我的 ProcessTicket.java 類

public class ProcessTicket {
    public static void main(String[] args) throws SQLException, SerialPortException {
 BarcodeScanner bSC = new BarcodeScanner();
        bSC.scannerHandler();
       BarcodeScanner.SerialPortReader portReader = new BarcodeScanner.SerialPortReader();
       ModelClass modelClass = new ModelClass();
       String value = modelClass.getBarcodeValue();
       System.out.println(value);
    }
}

這里的主要問題是您將固有的異步操作(從現實世界中的外部傳感器讀取)視為同步操作。

我模擬了外部傳感器的東西來制作一個獨立的應用程序來測試你的業務邏輯:

HowToRetrieveTheValueFromTheEventListenerFromAnotherClassInJava.java

package com.stackoverflow;

/**
 * https://stackoverflow.com/questions/57452205/how-to-retrieve-the-value-from-the-event-listener-from-another-class-in-java
 */
public class HowToRetrieveTheValueFromTheEventListenerFromAnotherClassInJava {

    public static void main(String[] args) {

        BarcodeScanner barcodeScanner = new BarcodeScanner((String barcode) -> {

            System.out.println("Barcode scanned: " + barcode);
        });

        barcodeScanner.startScan();

        MockUser.startScanningStuffLol();
    }
}

MockUser.startScanningStuffLol()調用只是必要的,因為我只是在代碼中測試它,而不使用真正的條形碼掃描儀。 請不要專注於此。 如果你問,我會發布它的實現,否則我假設你的操作系統/Java/硬件正在按照它們設計的方式工作,你可以用這些工具而不是我的MockUser軟件模擬來測試它。

以下是您需要實現的其余類:

BarcodeScannedCallback.java

package com.stackoverflow;

public interface BarcodeScannedCallback {

    void callback(String barcode);
}

因為我們正在處理一個異步操作,所以我們不能像處理同步操作那樣只啟動它然后檢查返回值。 相反,我們需要傳入一個在操作完成后將被調用的函數,然后等待它完成。 BarcodeScannedCallback是該函數的簽名(換句話說,該函數需要如何構建的描述)。 它接受一個字符串參數,不返回任何內容。

BarcodeScannedCallback的實現是我上面已經提到的這個函數,我將它傳遞給BarcodeScanner構造函數:

(String barcode) -> {
    System.out.println("Barcode scanned: " + barcode);
}

如您所見,該函數接受一個字符串參數,不返回任何內容。 因此,它是BarcodeScannedCallback接口的實現。

現在是最后一個類:使用上述接口橋接我們的main方法和串行端口的類。

BarcodeScanner.java

package com.stackoverflow;

public class BarcodeScanner implements SerialPortEventListener {

    private SerialPort serialPort;

    private final BarcodeScannedCallback callback;

    public void startScan() {

        try {

            serialPort = new SerialPort("COM4");
            serialPort.openPort();

            serialPort.addEventListener(this);

            // Also you can set params by this string: serialPort.setParams(9600, 8, 1, 0);
            serialPort.setParams(9600, 8, 1, 0);

            // Triggers barcode scanner.
            serialPort.writeString(new String(new byte[]{0x02}));

        } catch (SerialPortException ex) {

            System.out.println(ex);
        }
    }

    @Override
    public void serialEvent(SerialPortEvent event) {

        boolean isDataAvailable = event.isRXCHAR() && event.getEventValue() > 0;

        if (isDataAvailable) {

            try {

                byte[] bytesCont = serialPort.readBytes(14);
                String barcode = new String(bytesCont);

                callback.callback(barcode);

            } catch (SerialPortException ex) {

                System.out.println(ex);
            }
        }
    }

    public BarcodeScanner(BarcodeScannedCallback callback) {

        this.callback = callback;
    }
}

所以這里是這些事件的完整生命周期:

  • 您創建一個BarcodeScanner
  • 你告訴BarcodeScanner ,通過實施BarcodeScannedCallback您傳遞到它的構造,一旦接收到一個條形碼什么代碼運行在串行端口。
  • 你叫startScanBarcodeScanner ,打開串口,並開始等待用戶掃描條形碼。
  • 用戶掃描條形碼。 該數據通過串行端口傳輸。 操作系統的SerialPort實現調用BarcodeScanner.serialEvent
  • 您的serialEvent實現會進行驗證,從串行端口提取數據並將其從字節轉換為字符串,並調用開始時傳入的BarcodeScannedCallback函數。

當我運行它時(我的MockUser類設置了一個每 3 秒“掃描”一個條形碼的后台線程),我得到以下輸出:

Barcode scanned: 420L0L
Barcode scanned: 007
Barcode scanned: 12345

在您的情況下,您應該能夠使用真實世界的條碼掃描器掃描 3 個條碼,並獲得相同的結果。

請注意,您可能需要做一些事情來防止main方法的線程過早結束,具體取決於您運行它的上下文。

如果您在 Android 應用程序或 Web 服務器中運行它,這些框架會無限期地保持其主線程運行,直到您終止應用程序/服務器。

但是,如果您將它作為自定義命令行應用程序運行(基於main方法的存在,您似乎正在這樣做),您將需要做一些事情以使其保持活動狀態,直到您決定殺死它. 最簡單的方法就是像while (true);那樣放一個無限循環while (true); main方法的最后一行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM