簡體   English   中英

為什么onReceive()被多次調用?

[英]why onReceive() is being called many times?

我不知道為什么當我連接或斷開wifi時,wifi接收器下面發布的代碼中的相應回調至少被多次調用了三次,並且

因此,如果我想基於當前的wifi狀態調用一個函數,該函數將被調用很多次,而我不希望這樣的行為,尤其是在

有wifi連接時應調用的功能,我正在顯示一個對話框,並且由於該回調將被調用多次,該對話框將被調用多次,因此會導致重疊。

請在下面發布的logcat上進行操作,這只是我得到的示例。

請讓我知道為什么wifi狀態對應的回調多次被調用,如何避免這種多次調用?

代碼

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);

    tv_status = (TextView) findViewById(R.id.tv_status);

    this.registerReceiver(this.myWifiReceiver, new IntentFilter(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION));
}

private BroadcastReceiver myWifiReceiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
        Log.d(TAG, "@onReceive()");

        mConnMgr = (ConnectivityManager)getSystemService(network_service);
        WifiManager wifiMgr = (WifiManager) context.getSystemService(WiFi_Service);

        switch (wifiMgr.getWifiState()) {
        case WifiManager.WIFI_STATE_ENABLED:
            Log.d(TAG, "wifi enabled");

            if (mConnMgr != null) {
                networkInfo = mConnMgr.getActiveNetworkInfo();
                if (networkInfo != null) {
                    switch(networkInfo.getType()) {
                    case ConnectivityManager.TYPE_WIFI: 
                        if (networkInfo.isConnected()) {
                            tv_status.setText("Connected");
                            Log.d(TAG, "Connected");
                        }else if (networkInfo.isConnectedOrConnecting()) {
                            tv_status.setText("Status: CONNECTED Or CONNECTING");
                            Log.d(TAG, "Status: CONNECTED Or CONNECTING");
                        }else if (networkInfo.isFailover()){
                            Log.d(TAG, "Status: FailOver");
                        }else if (networkInfo.isRoaming()) {
                            Log.d(TAG, "Status: Roaming");
                        }else if (networkInfo.isAvailable()) {
                            Log.d(TAG, "Status: Available");
                        } else {
                            Log.d(TAG, "Status: disconnected");
                        }
                        break;

                    }
                }else {
                    tv_status.setText("Status: No Default NetWork Connected");
                    Log.d(TAG, "Status: No Default NetWork Connected");
                }
            } else {
                tv_status.setText("Status:  ConnMgr is null");
                Log.d(TAG, "Status:  ConnMgr is null");
            }

            break;

LogCat

03-04 15:31:31.031: D/MainActivity(16120): @onReceive()
03-04 15:31:31.031: D/MainActivity(16120): wifi enabled
03-04 15:31:31.032: D/MainActivity(16120): Status: No Default NetWork Connected
03-04 15:31:31.546: D/MainActivity(16120): @onReceive()
03-04 15:31:31.547: D/MainActivity(16120): wifi enabled
03-04 15:31:31.547: D/MainActivity(16120): Status: No Default NetWork Connected
03-04 15:31:31.617: D/MainActivity(16120): @onReceive()
03-04 15:31:31.618: D/MainActivity(16120): wifi enabled
03-04 15:31:31.620: D/MainActivity(16120): Status: No Default NetWork Connected
03-04 15:31:31.636: D/MainActivity(16120): @onReceive()
03-04 15:31:31.636: D/MainActivity(16120): wifi enabled
03-04 15:31:31.637: D/MainActivity(16120): Status: No Default NetWork Connected
03-04 15:32:28.661: D/MainActivity(16120): @onReceive()
03-04 15:32:28.663: D/MainActivity(16120): wifi enabled
03-04 15:32:28.666: D/MainActivity(16120): Status: No Default NetWork Connected
03-04 15:32:28.708: D/MainActivity(16120): @onReceive()
03-04 15:32:28.709: D/MainActivity(16120): wifi enabled
03-04 15:32:28.710: D/MainActivity(16120): Status: No Default NetWork Connected
03-04 15:32:28.722: D/MainActivity(16120): @onReceive()
03-04 15:32:28.722: D/MainActivity(16120): wifi enabled
03-04 15:32:28.722: D/MainActivity(16120): Status: No Default NetWork Connected

Update_1

使用計時器的MySolution

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);

    tv_status = (TextView) findViewById(R.id.tv_status);
    IntentFilter intfil = new IntentFilter(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);

    this.registerReceiver(this.myWifiReceiver, intfil);
}

private BroadcastReceiver myWifiReceiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
        Log.d(TAG, "@onReceive()");
        Timer t1 = new Timer();
        Timer t2 = new Timer();

        if (!locked) {
            if (scheduled1) {
                t1.cancel();
                t1.purge();
            }
            if (scheduled2) {
                t2.cancel();
                t2.purge();
            }

            WifiManager wifiMgr = (WifiManager) context.getSystemService(WiFi_Service);

            switch (wifiMgr.getWifiState()) {
            case WifiManager.WIFI_STATE_ENABLED:
                Log.d(TAG, "wifi enabled");
                locked = true;
                t1 = new Timer();
                t1.schedule(MQTTReceiverLockTimedTask, 4000);
                scheduled1 = true;
                module();
                break;

            case WifiManager.WIFI_STATE_DISABLED:
                Log.d(TAG, "wifi disabled");
                locked = true;
                t2 = new Timer();
                t2.schedule(MQTTReceiverLockTimedTask, 4000);
                scheduled2 = true;
                break;
            }
        }
    }
};

TimerTask MQTTReceiverLockTimedTask = new TimerTask() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        locked = false;
    }
};

protected void module() {
    // TODO Auto-generated method stub
    mConnMgr = (ConnectivityManager)getSystemService(network_service);

    if (mConnMgr != null) {
        networkInfo = mConnMgr.getActiveNetworkInfo();
        if (networkInfo != null) {
            switch(networkInfo.getType()) {
            case ConnectivityManager.TYPE_WIFI: 
                if (networkInfo.isConnected()) {
                    tv_status.setText("Connected");
                    Log.d(TAG, "Connected");
                }else if (networkInfo.isConnectedOrConnecting()) {
                    tv_status.setText("Status: CONNECTED Or CONNECTING");
                    Log.d(TAG, "Status: CONNECTED Or CONNECTING");
                }else if (networkInfo.isFailover()){
                    Log.d(TAG, "Status: FailOver");
                }else if (networkInfo.isRoaming()) {
                    Log.d(TAG, "Status: Roaming");
                }else if (networkInfo.isAvailable()) {
                    Log.d(TAG, "Status: Available");
                } else {
                    Log.d(TAG, "Status: disconnected");
                }
                break;

            }
        }else {
            tv_status.setText("Status: No Default NetWork Connected");
            Log.d(TAG, "Status: No Default NetWork Connected");
        }
    } else {
        tv_status.setText("Status:  ConnMgr is null");
        Log.d(TAG, "Status:  ConnMgr is null");
    }
}

WifiManager文檔WifiManager.SUPPLICANT_STATE_CHANGED_ACTION

廣播意圖動作,指示與接入點建立連接的狀態已更改。另外一個提供了新的SupplicantState。

由於SupplicantState提供了有關建立連接狀態的更詳細的信息,因此您會收到許多對onReceive()調用。 每次此狀態更改時,都會廣播一個新的意圖。 由於您只需要較少的詳細信息,因此看來您獲得了許多相同的廣播。

關於如何避免這種情況的方法:搜索另一種收聽意圖,例如ConnectivityManager.CONNECTIVITY_ACTION如果它滿足您的需要),或嘗試Mahmoud Elmorabea的解決方案-將當前的wifi連接狀態保存在Activity類以及onReceive() ,檢查連接狀態是否已更改。 如果還沒有,請跳過其余代碼。 否則,請運行代碼並更新您的狀態。 如果使用此解決方案,請記住在“活動”生命周期中保存“狀態”字段。

將WiFi的當前狀態保存在某個地方,某個管理器或其他某個位置,並且僅當以與當前狀態不同的狀態調用onReceive()時才執行代碼。

假設您在活動中使用此代碼。

在您的活動中,您將擁有一個稱為currentWifiState的屬性,起初它等於-100; 例如

在您的接收器中,代碼如下所示

if (wifiManager.getWifiState() == currentWifiState)
     return;

然后,如果您要通知的狀態與當前狀態相同,則您將不執行任何操作。

除非Wifi狀態更改,否則您的代碼將不會執行。

暫無
暫無

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

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