簡體   English   中英

EventChannel 不是每次都被調用

[英]EventChannel not being called every time

我對 flutter+dart 框架很陌生。 我試圖了解EventChannel的工作原理。 我已經設置了EventChannel來捕獲來電號碼。

android這邊,我設置了一個BroadcastReceiver如下。

public class CallEventHandler extends BroadcastReceiver implements EventChannel.StreamHandler {
private static final String TAG = "[SAMPLE]";
private static final int NUMBER_LEN = 10;

private EventChannel.EventSink eventSink = null;
private Activity activity = null;

public CallEventHandler(Activity activity) {
    this.activity = activity;
}
@Override
public void onListen(Object arguments, EventChannel.EventSink events) {
    Log.i(TAG, "[onListen] setting up events");
    eventSink = events;
}

@Override
public void onCancel(Object arguments) {
    Log.i(TAG, "[onCancel] cancel events");
    eventSink = null;
    activity = null;
}

@Override
public void onReceive(Context context, Intent intent) {
    try {
        String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
        String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
        if(state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
            if(incomingNumber != null) {
                Log.i(TAG, "[CallEventHandler] Incoming number : " + incomingNumber);
                if(incomingNumber.length() > NUMBER_LEN) {
                    incomingNumber = incomingNumber.substring(incomingNumber.length() - NUMBER_LEN, incomingNumber.length());
                    Log.i(TAG, "[CallEventHandler] Incoming number after : " + incomingNumber);
                    if(activity != null) {
                        String finalIncomingNumber = incomingNumber;
                        activity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if(eventSink != null) {
                                    Log.i(TAG, "[CallEventHandler] HERESSSSS : " + finalIncomingNumber);
                                    eventSink.success(finalIncomingNumber);
                                }
                            }
                        });
                    }
                }
            }
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

}

onReceive方法中,我獲取傳入號碼並將其發送到EventSink

在我的MainActivity中,我按如下方式設置CallEventHandler

private final String eventId = "SAMPLE_ID";
private CallEventHandler handler = new CallEventHandler(this);

@Override
public void onStart() {
    super.onStart();
    ...
    registerReceiver(handler, filter);
}

@Override
public void onStop() {
    super.onStop();
    unregisterReceiver(handler);
}

@Override
public void configureFlutterEngine(@NonNull  FlutterEngine flutterEngine) {
    super.configureFlutterEngine(flutterEngine);
    new EventChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), eventId)
            .setStreamHandler(handler);
}

Flutter這邊,代碼如下:

class EventHandler {
    static const String TAG = "[SAMPLE]";
    final String _eventId = "SAMPLE_ID";
    EventChannel? _evtChannel;
    Stream<String>? _evtStream;

    EventHandler() {
        debugPrint(TAG + " Setting up EventHandler");
        _evtChannel = EventChannel(_eventId);
        _evtStream = _evtChannel?.receiveBroadcastStream().distinct().map((dynamic
        event) => getString(event as String));
    }

    void startListening(void Function(String data)? onData) {
        debugPrint(TAG + " starting listening");
        _evtStream?.listen((data) {
            debugPrint(TAG + " In listening");
            onData!(data);
        });
    }
}

在我的 UI 代碼中,我有一個StatefulWidget (MySamplePage),我在收到調用時在其中注冊我的回調

void initState() {
    widget.handler.startListening((incomingNumber) {
      debugPrint(_tag + " data : $incomingNumber");
      ...
    }); 
}

在我的有狀態主頁構建方法中,我在initState中初始化處理程序並在build方法中添加route

class _HomeScreenState extends State<HomeScreen> {
    @override
    void initState() {
        super.initState();
        debugPrint(_tag + "initState");
        _handler = EventHandler();
    }

    @override
    Widget build(BuildContext context) {
        return MaterialApp(
            routes: {
                '/caller': (context) => MySamplePage(
                    handler: _handler
                 ),
            },
            ...
        );
    }
}

我面臨的問題是,當小部件打開時,我收到了第一個來電,正如預期的那樣。 但是,如果我再打一個電話,那么第二個電話就不會被 stream 捕獲。如果我按下后退按鈕,然后重新打開小部件,一切都會按預期進行,第一個來電將打印在控制台中。 我知道 Android 代碼正在從onReceive方法發送事件(每次都會打印“HERESSSSS”行),但是 flutter stream 沒有獲取值。 我不確定我在這里做錯了什么。 有人可以幫忙嗎?

我的日志是

I/flutter (11836): [SAMPLE][HomeScreen]initState
I/flutter (11836): [SAMPLE][EventHandler] Setting up EventHandler
V/AutofillManager(11836): requestHideFillUi(null): anchor = null
I/flutter (11836): [SAMPLE][EventHandler] starting listening
I/[SAMPLE] (11836): [onListen] setting up events
I/[SAMPLE] (11836): [CallEventHandler] Receiver start
I/[SAMPLE] (11836): [CallEventHandler] Receiver start
I/[SAMPLE] (11836): [CallEventHandler] Incoming number : +91XXXXXXXXXX
I/[SAMPLE] (11836): [CallEventHandler] Incoming number after : XXXXXXXXXX
I/[SAMPLE] (11836): [CallEventHandler] HERESSSSS : XXXXXXXXXX
I/flutter (11836): [SAMPLE][EventHandler] In listening
I/flutter (11836): [SAMPLE] data : XXXXXXXXXX

在隨后的來電中,不打印最后一行

謝謝

好的,我已經設法解決了它,但不知道這是否是正確的方法。 問題是MySamplePage是一個StatefulWidget ,我在其State object 中調用setState 。這可能是它無法再收聽 stream 的原因。 我已經調用startListeningsetState方法並相應地更改了代碼(刪除之前的訂閱並重新收聽流)

void startListening(void Function(String data)? onData) {
    debugPrint(TAG + " starting listening");
    if(_subscription != null) {
        _subscription?.cancel();
        _subscription = null;
    }
    _subscription ??= _evtStream?.listen((data) {
        debugPrint(TAG + " In listening");
        onData!(data);
    });
}

這里_subscriptionStreamSubscription<String>? . 希望這個答案有幫助。 我應該早點發布完整的代碼。

暫無
暫無

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

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