You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native多屏使用Zebra DataWedge Intent初始化耗时倍增问题

问题分析与解决方案

问题概述

我们开发了一款包含多个扫描组件页面的扫描APP。首次加载首页的扫描组件时初始化耗时正常,但在页面间切换时,每次初始化耗时都会比上一次翻倍。扫描功能可正常工作,仅存在页面切换时初始化时长倍增的问题。

设备与依赖信息

  • 设备:Zebra ET40
  • DataWedge版本:11.3
  • 依赖包:"react-native-datawedge-intents": "^0.1.8"

问题根源

查看你的ZebraScanner组件代码,发现组件卸载时没有清理注册的事件监听器和广播接收器:

  1. 在constructor中通过DeviceEventEmitter.addListener添加了datawedge_broadcast_intent的监听器,但未在组件销毁时移除
  2. 调用DataWedgeIntents.registerBroadcastReceiver注册了广播接收器,但未注销

每次页面切换,旧的ZebraScanner组件实例被销毁,但监听器和广播接收器依然留存;新实例创建时又会重复注册,导致监听器和广播接收器数量随页面切换次数递增。每次初始化时,DataWedge的广播会被多个监听器处理,最终导致初始化耗时翻倍增长。

修复方案

在ZebraScanner组件中添加componentWillUnmount生命周期方法,清理注册的监听器和广播接收器:

import React, { Component } from 'react';
import { DeviceEventEmitter } from 'react-native';
import DataWedgeIntents from 'react-native-datawedge-intents';
import { EventRegister } from 'react-native-event-listeners';

type Props = {
    onScanned: Function,
};

type State = {
    ean8checked: boolean,
    ean13checked: boolean,
    code39checked: boolean,
    code128checked: boolean,
    lastApiVisible: boolean,
    lastApiText: string,
    checkBoxesDisabled: boolean,
    scanButtonVisible: boolean,
    dwVersionText: string,
    activeProfileText: string,
    enumeratedScannersText: string,
    scans: [],
};

export default class ZebraScanner extends Component<Props, State> {
    sendCommandResult: string;
    broadcastReceiverHandler: (intent: any) => void;
    // 保存监听器引用,方便后续移除
    datawedgeListener: any;

    constructor(props: Props) {
        super(props)
        this.state = {
            ean8checked: true,
            ean13checked: true,
            code39checked: true,
            code128checked: true,
            lastApiVisible: false,
            lastApiText: "Messages from DataWedge will go here",
            checkBoxesDisabled: true,
            scanButtonVisible: false,
            dwVersionText: "Pre 6.3.  Please create and configure profile manually.  See the ReadMe for more details",
            activeProfileText: "Requires DataWedge 6.3+",
            enumeratedScannersText: "Requires DataWedge 6.3+",
            scans: [],
        };
        this.sendCommandResult = "false";
        this.broadcastReceiverHandler = (intent) => {
            this.broadcastReceiver(intent);
        }
        // 保存监听器引用
        this.datawedgeListener = DeviceEventEmitter.addListener('datawedge_broadcast_intent', this.broadcastReceiverHandler);
        this.registerBroadcastReceiver();
        this.determineVersion();
    }

    // 组件卸载时清理资源
    componentWillUnmount() {
        // 移除DeviceEventEmitter监听器
        if (this.datawedgeListener) {
            this.datawedgeListener.remove();
        }
        // 注销广播接收器
        DataWedgeIntents.unregisterBroadcastReceiver();
    }

    _onPressScanButton() {
        this.sendCommand("com.symbol.datawedge.api.SOFT_SCAN_TRIGGER", 'TOGGLE_SCANNING');
    }

    determineVersion() {
        this.sendCommand("com.symbol.datawedge.api.GET_VERSION_INFO", "");
    }

    setDecoders() {
        var profileConfig = {
            "PROFILE_NAME": "ScannerDemo",
            "PROFILE_ENABLED": "true",
            "CONFIG_MODE": "UPDATE",
            "PLUGIN_CONFIG": {
                "PLUGIN_NAME": "BARCODE",
                "PARAM_LIST": {
                    "scanner_selection": "auto",
                    "decoder_ean8": "" + this.state.ean8checked,
                    "decoder_ean13": "" + this.state.ean13checked,
                    "decoder_code128": "" + this.state.code128checked,
                    "decoder_code39": "" + this.state.code39checked
                }
            }
        };
        this.sendCommand("com.symbol.datawedge.api.SET_CONFIG", profileConfig);
    }

    sendCommand(extraName: string, extraValue: any) {
        const broadcastExtras: any = {};
        broadcastExtras[extraName] = extraValue;
        broadcastExtras["SEND_RESULT"] = this.sendCommandResult;
        DataWedgeIntents.sendBroadcastWithExtras({
            action: "com.symbol.datawedge.api.ACTION",
            extras: broadcastExtras
        });
    }

    registerBroadcastReceiver() {
        DataWedgeIntents.registerBroadcastReceiver({
            filterActions: [
                'com.zebra.reactnativedemo.ACTION',
                'com.symbol.datawedge.api.RESULT_ACTION'
            ],
            filterCategories: [
                'android.intent.category.DEFAULT'
            ]
        });
    }

    broadcastReceiver(intent: any) {
        if (intent.hasOwnProperty('RESULT_INFO')) {
            const commandResult = intent.RESULT + " (" +
                intent.COMMAND.substring(intent.COMMAND.lastIndexOf('.') + 1, intent.COMMAND.length) + ")";
            this.commandReceived(commandResult.toLowerCase());
        }

        if (intent.hasOwnProperty('com.symbol.datawedge.api.RESULT_GET_VERSION_INFO')) {
            const versionInfo = intent['com.symbol.datawedge.api.RESULT_GET_VERSION_INFO'];
            const datawedgeVersion = versionInfo['DATAWEDGE'];

            if (datawedgeVersion >= "11.3")
                this.datawedge113();

            this.setState(this.state);
        } else if (intent.hasOwnProperty('com.symbol.datawedge.api.RESULT_ENUMERATE_SCANNERS')) {
            const enumeratedScannersObj = intent['com.symbol.datawedge.api.RESULT_ENUMERATE_SCANNERS'];
            this.enumerateScanners(enumeratedScannersObj);
        } else if (intent.hasOwnProperty('com.symbol.datawedge.api.RESULT_GET_ACTIVE_PROFILE')) {
            const activeProfileObj = intent['com.symbol.datawedge.api.RESULT_GET_ACTIVE_PROFILE'];
            this.activeProfile(activeProfileObj);
        } else if (!intent.hasOwnProperty('RESULT_INFO')) {
            this.barcodeScanned(intent, new Date().toLocaleString());
        }
    }

    datawedge113() {
        this.sendCommand("com.symbol.datawedge.api.CREATE_PROFILE", "ScannerDemo");

        this.setState({
            dwVersionText: "11.3",
            checkBoxesDisabled: false
        });

        var profileConfig = {
            "PROFILE_NAME": "ScannerDemo",
            "PROFILE_ENABLED": "true",
            "CONFIG_MODE": "UPDATE",
            "PLUGIN_CONFIG": {
                "PLUGIN_NAME": "BARCODE",
                "RESET_CONFIG": "true",
                "PARAM_LIST": {
                    "configure_all_scanners": 'true',
                    "scanner_input_enabled": 'true',
                    "aim_type": '3',
                    "EXTRA_DATA": {
                        "aim_type": '3',
                    }
                }
            },
            "APP_LIST": [{
                "PACKAGE_NAME": "com.datawedgereactnative.demo",
                "ACTIVITY_LIST": ["*"]
            },
            {
                "PACKAGE_NAME": "com.demo",
                "ACTIVITY_LIST": ["*"]
            }]
        };
        this.sendCommand("com.symbol.datawedge.api.SET_CONFIG", profileConfig);

        var profileConfig2 = {
            "PROFILE_NAME": "ScannerDemo",
            "PROFILE_ENABLED": "true",
            "CONFIG_MODE": "UPDATE",
            "PLUGIN_CONFIG": {
                "PLUGIN_NAME": "INTENT",
                "RESET_CONFIG": "true",
                "PARAM_LIST": {
                    "intent_output_enabled": "true",
                    "intent_action": "com.zebra.reactnativedemo.ACTION",
                    "intent_delivery": "2"
                }
            }
        };
        this.sendCommand("com.symbol.datawedge.api.SET_CONFIG", profileConfig2);
        
        setTimeout(() => {
            this.sendCommand("com.symbol.datawedge.api.GET_ACTIVE_PROFILE", "");
            this.sendCommand("com.symbol.datawedge.api.ENUMERATE_SCANNERS", "");
        }, 1000);
    }

    commandReceived(commandText: string) {
        this.setState({
            lastApiText: commandText
        });
        this.setState(this.state);
    }

    enumerateScanners(enumeratedScanners: any) {
        let humanReadableScannerList: string = "";
        for (let i = 0; i < enumeratedScanners.length; i++) {
            humanReadableScannerList += enumeratedScanners[i].SCANNER_NAME;
            if (i < enumeratedScanners.length - 1)
                humanReadableScannerList += ", ";
        }
        this.setState({
            enumeratedScannersText: humanReadableScannerList,
        })
    }

    activeProfile(theActiveProfile: any) {
        this.setState({
            activeProfileText: theActiveProfile
        });
        this.setState(this.state);
    }

    barcodeScanned(scanData: any, timeOfScan: any) {
        const scannedData = scanData["com.symbol.datawedge.data_string"];
        EventRegister.emit('barcode_scanned', scannedData);
    }

    render() {
        return (<></>);
    }
}

额外优化建议

  • 避免重复创建DataWedge配置:当前datawedge113方法每次组件初始化都会重新创建和配置ScannerDemo profile,可添加判断逻辑,仅在profile不存在时执行创建配置操作,减少不必要的DataWedge交互
  • 简化状态更新:代码中多处出现this.setState(this.state)的无效更新,可直接移除,避免不必要的组件重渲染

内容的提问来源于stack exchange,提问作者Shailesh Daund

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 22:19:50