Android相当于NSNotificationCenter

Joh*_*ohn 92 iphone events android nsnotificationcenter ios

在将iPhone应用程序移植到android的过程中,我正在寻找在应用程序内进行通信的最佳方式.意图似乎是要走的路,这是最好的(唯一的)选择吗?NSUserDefaults在性能和编码方面的重量似乎比Intents轻得多.

我还应该添加我有一个状态的应用程序子类,但我需要让另一个活动知道一个事件.

Shi*_*iki 337

我找到的最好的等价物是LocalBroadcastManager,它是Android支持包的一部分.

从LocalBroadcastManager文档:

帮助程序注册并向您的进程中的本地对象发送Intent广播.与使用sendBroadcast(Intent)发送全局广播相比,这有许多优点:

  • 您知道您正在播放的数据不会离开您的应用,因此无需担心泄露私人数据.
  • 其他应用程序无法将这些广播发送到您的应用程序,因此您无需担心他们可以利用安全漏洞.
  • 它比通过系统发送全局广播更有效.

使用它时,你可以说Intenta等同于NSNotification.这是一个例子:

ReceiverActivity.java

监视名为的事件的通知的活动"custom-event-name".

@Override
public void onCreate(Bundle savedInstanceState) {

  ...

  // Register to receive messages.
  // This is just like [[NSNotificationCenter defaultCenter] addObserver:...]
  // We are registering an observer (mMessageReceiver) to receive Intents
  // with actions named "custom-event-name".
  LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
      new IntentFilter("custom-event-name"));
}

// Our handler for received Intents. This will be called whenever an Intent
// with an action named "custom-event-name" is broadcasted.
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    // Get extra data included in the Intent
    String message = intent.getStringExtra("message");
    Log.d("receiver", "Got message: " + message);
  }
};

@Override
protected void onDestroy() {
  // Unregister since the activity is about to be closed.
  // This is somewhat like [[NSNotificationCenter defaultCenter] removeObserver:name:object:] 
  LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
  super.onDestroy();
}
Run Code Online (Sandbox Code Playgroud)

SenderActivity.java

发送/广播通知的第二个活动.

@Override
public void onCreate(Bundle savedInstanceState) {

  ...

  // Every time a button is clicked, we want to broadcast a notification.
  findViewById(R.id.button_send).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      sendMessage();
    }
  });
}

// Send an Intent with an action named "custom-event-name". The Intent sent should 
// be received by the ReceiverActivity.
private void sendMessage() {
  Log.d("sender", "Broadcasting message");
  Intent intent = new Intent("custom-event-name");
  // You can also include some extra data.
  intent.putExtra("message", "This is my message!");
  LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
Run Code Online (Sandbox Code Playgroud)

使用上面的代码,每次R.id.button_send单击按钮时,都会广播一个Intent并由mMessageReceiverin 接收ReceiverActivity.

调试输出应如下所示:

01-16 10:35:42.413: D/sender(356): Broadcasting message
01-16 10:35:42.421: D/receiver(356): Got message: This is my message! 
Run Code Online (Sandbox Code Playgroud)

  • 您可能不应该在onCreate方法中调用registerReceiver,因为这会泄漏您的Activity并且您的onDestroy方法永远不会被调用.onResume似乎是调用registerReceiver和onPause调用unregisterReceiver的更好选择. (14认同)
  • 非常感谢您抽出宝贵时间撰写如此有用,详尽的回复. (10认同)
  • 完美相当于"NSNotificationCenter",应该是公认的答案! (4认同)

Elv*_*nja 14

这里有类似于@Shiki的答案,但是从iOS开发者和通知中心的角度来看.

首先创建一些NotificationCenter服务:

public class NotificationCenter {

 public static void addObserver(Context context, NotificationType notification, BroadcastReceiver responseHandler) {
    LocalBroadcastManager.getInstance(context).registerReceiver(responseHandler, new IntentFilter(notification.name()));
 }

 public static void removeObserver(Context context, BroadcastReceiver responseHandler) {
    LocalBroadcastManager.getInstance(context).unregisterReceiver(responseHandler);
 }

 public static void postNotification(Context context, NotificationType notification, HashMap<String, String> params) {
    Intent intent = new Intent(notification.name());
    // insert parameters if needed
    for(Map.Entry<String, String> entry : params.entrySet()) {
        String key = entry.getKey();
        String value = entry.getValue();
        intent.putExtra(key, value);
    }
    LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
 }
}
Run Code Online (Sandbox Code Playgroud)

然后,您还需要一些枚举类型来确保使用字符串编码时出错 - (NotificationType):

public enum NotificationType {

   LoginResponse;
   // Others

}
Run Code Online (Sandbox Code Playgroud)

以下是在活动中的用法(添加/删除观察者):

public class LoginActivity extends AppCompatActivity{

    private BroadcastReceiver loginResponseReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
           // do what you need to do with parameters that you sent with notification

           //here is example how to get parameter "isSuccess" that is sent with notification
           Boolean result = Boolean.valueOf(intent.getStringExtra("isSuccess"));
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        //subscribe to notifications listener in onCreate of activity
        NotificationCenter.addObserver(this, NotificationType.LoginResponse, loginResponseReceiver);
    }

    @Override
    protected void onDestroy() {
        // Don't forget to unsubscribe from notifications listener
        NotificationCenter.removeObserver(this, loginResponseReceiver);
        super.onDestroy();
    }
}
Run Code Online (Sandbox Code Playgroud)

最后我们将通过一些回调或休息服务或其他方式向NotificationCenter发布通知:

public void loginService(final Context context, String username, String password) {
    //do some async work, or rest call etc.
    //...

    //on response, when we want to trigger and send notification that our job is finished
    HashMap<String,String> params = new HashMap<String, String>();          
    params.put("isSuccess", String.valueOf(false));
    NotificationCenter.postNotification(context, NotificationType.LoginResponse, params);
}
Run Code Online (Sandbox Code Playgroud)

就是这样,欢呼!


Rui*_*res 6

你可以尝试这个:http://developer.android.com/reference/java/util/Observer.html

  • Shiki在下面的答案要好得多. (40认同)
  • @dsaff尽管是一个更完整的答案,我的答案绝对不对,我显然不值得-1.什么是有意义的,你可以+1 Shiki的答案. (5认同)
  • 请注意,只有技术上不正确和垃圾邮件的答案才应该被低估 - 这两者都不适用.赔偿+1,Shiki +1,因为这是一个很好的答案. (4认同)
  • Shiki是这个问题的更好答案 (3认同)

Shl*_*sin 6

我发现使用 Guava lib 的 EventBus 是组件之间进行发布-订阅式通信的最简单方法,而不需要组件之间显式注册

请参阅https://code.google.com/p/guava-libraries/wiki/EventBusExplained上的示例

// Class is typically registered by the container.
class EventBusChangeRecorder {
  @Subscribe public void recordCustomerChange(ChangeEvent e) {
    recordChange(e.getChange());
  }

// somewhere during initialization
eventBus.register(this);

}

// much later
public void changeCustomer() {
  eventBus.post(new ChangeEvent("bla bla") );
} 
Run Code Online (Sandbox Code Playgroud)

您可以通过向 build.gradle 添加依赖项来简单地在 Android Studio 上添加此库:

compile 'com.google.guava:guava:17.0'
Run Code Online (Sandbox Code Playgroud)