从singleton注册BroadcastReceivers

时间:2014-07-30 09:18:41

标签: android

我正在尝试创建一个单例类来报告连接状态。我的想法是,我可以在我的应用程序中的任何地方重复使用这个“服务”,例如:

getApplication().getConnectivityStatus().isConnected()

单例具有对ApplicationContext的引用。

我想在幕后使用BroadcastReceiver来检测连接变化。我正在连接“服务”中动态注册和取消注册,以实现更高级别的连接侦听器,例如:

getApplication().getConnectivityStatus().onConnectivity(mConnectivityCallback)

我只希望我自行决定注册BroadcastReceiver。但是,当应用程序被杀时,我在这里看到了一个洞。由于Application没有生命周期回调,如果应用程序被杀死,我无法挂钩取消注册BroadcastReceiver。

所以,1:我的应用程序死了,但是BroadcastReceiver(及其对ApplicationContext的引用)仍然被注册,并且它的onReceive方法被调用...会发生坏事吗?

2:有没有办法干净地做我想做的事情,或者我的模式是不是被误解了?

2 个答案:

答案 0 :(得分:1)

我只想在BroadcastReceiver中创建AndroidManifest.xml registered

从该接收器,您可以更新单身人士的连接状态,并且您不必担心取消注册。如果您不希望其他类能够更改状态,请将接收器和单例类放在单独的包中,并仅对该包进行setter方法可见性。

<强>更新

你的想法听起来非常有趣,拥有密封的服务&#34;处理网络更改并通知已注册的侦听器。但是,最后你的听众是Activites,这意味着一次总会有一个听众。此外,您不能在长期存在的对象中保留对Activity的强引用,并且必须使用Activite的生命周期回调。

我得出的结论是,你可以更好地使用经理类的非常简单的模式(我曾经实现过)。

Manager类看起来像这样:

public class NetworkManager {

    private boolean connected;
    private NetworkCallback callback;

    private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            updateStatus(context);
        }
    };

    private void updateStatus(Context context) {
        ConnectivityManager conn = (ConnectivityManager)
                context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = conn.getActiveNetworkInfo();
        //TODO do the rest here, e.g. set connected flag
        connected = networkInfo.isConnected();
        if (callback != null) {
            callback.onConnectionChanged(connected);
        }
    }

    public void registerContext(Context context, NetworkCallback callback) {
        this.callback = callback;
        IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        context.registerReceiver(receiver, filter);
        updateStatus(context);
    }

    public void unregisterContext(Context context) {
        callback = null;
        context.unregisterReceiver(receiver);
    }

    public interface NetworkCallback {

        void onConnectionChanged(boolean connected);
    }
}

如果它仅被“活动”使用,则不必是单身人士。

使用它的活动:

public class NetworkActivity extends Activity implements NetworkManager.NetworkCallback {

    private NetworkManager networkManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);
        networkManager = new NetworkManager();
    }

    @Override
    protected void onResume() {
        super.onResume();
        networkManager.registerContext(this, this);
    }

    @Override
    protected void onPause() {
        networkManager.unregisterContext(this);
        super.onPause();
    }

    @Override
    public void onConnectionChanged(boolean connected) {
        //TODO do something here
    }
}

<强>提示

不要强迫自己使用不需要的复杂模式创建代码。仅在您的应用程序实际受益于其优势时才使用模式。

答案 1 :(得分:-1)

这里发布了通过服务测试互联网连接的示例代码,让用户知道是否通过服务存在网络可能会对您有所帮助

BroadcastReceiverClass.java

    package com.sample;

import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.widget.Toast;

public class BroadcastReceiverClass extends android.content.BroadcastReceiver {

    Context _con;

    public BroadcastReceiverClass(Context _con) {
        this._con = _con;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
        intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
        intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);

        NetworkInfo currentNetworkInfo = (NetworkInfo) intent
                .getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
        intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);

        if (currentNetworkInfo.isConnected()) {
            Toast.makeText(_con, "Connected", Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(_con, "Not Connected", Toast.LENGTH_LONG).show();
        }
    }
}

/////////////////////////////////////////////// //////////////////////////

BroadCastSampleActivity .java

package com.sample;
import android.app.Activity;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.Bundle;

public class BroadCastSampleActivity extends Activity {
    BroadcastReceiverClass mConnReceiver;

    /** Called when the activity is first created. */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        mConnReceiver = new BroadcastReceiverClass(this);
        this.registerReceiver(mConnReceiver, new IntentFilter(
                ConnectivityManager.CONNECTIVITY_ACTION));

    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();

        // this.unregisterReceiver(mConnReceiver);
    }

    // private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
    // public void onReceive(Context context, Intent intent) {
    // intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,
    // false);
    // intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
    // intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);
    //
    // NetworkInfo currentNetworkInfo = (NetworkInfo) intent
    // .getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
    // intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
    //
    // if (currentNetworkInfo.isConnected()) {
    // Toast.makeText(getApplicationContext(), "Connected",
    // Toast.LENGTH_LONG).show();
    // } else {
    // Toast.makeText(getApplicationContext(), "Not Connected",
    // Toast.LENGTH_LONG).show();
    // }
    // }
    // };
}

///////////////////////////////////////////// 清单

    <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.sample"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/ic_launcher" android:label="@string/app_name">
        <activity android:name=".BroadCastSampleActivity"
                  android:label="BroadCast">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-sdk android:minSdkVersion="9" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>