Android相当于NSNotificationCenter

Android相当于NSNotificationCenter,android,iphone,ios,events,nsnotificationcenter,Android,Iphone,Ios,Events,Nsnotificationcenter,在将iPhone应用程序移植到android的过程中,我正在寻找在应用程序内进行通信的最佳方式。意图似乎是一条路,这是最好(唯一)的选择吗?NSUserDefaults在性能和编码方面似乎比Intent轻得多 我还应该为state添加一个应用程序子类,但我需要让另一个活动知道一个事件。您可以尝试以下操作:您可以使用此:,它提供了类似的行为 您可以通过Context.registerReceiver(BroadcastReceiver,IntentFilter)以编程方式注册接收者,它将捕获通过C

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

我还应该为state添加一个应用程序子类,但我需要让另一个活动知道一个事件。

您可以尝试以下操作:

您可以使用此:,它提供了类似的行为

您可以通过Context.registerReceiver(BroadcastReceiver,IntentFilter)以编程方式注册接收者,它将捕获通过Context.sendBroadcast(Intent)发送的意图


但是请注意,如果接收器的活动(上下文)已暂停,则不会收到通知

我找到的最好的等价物是

从LocalBroadcastManager文档:

助手,用于注册并向进程内的本地对象发送意图广播。与使用sendBroadcast(意图)发送全局广播相比,这具有许多优势:

  • 你知道你正在广播的数据不会离开你的应用程序,所以不必担心泄露私人数据
  • 其他应用程序不可能将这些广播发送到您的应用程序,因此您无需担心它们会利用安全漏洞
  • 它比通过系统发送全球广播更有效
使用此选项时,可以说
意图
等同于
通知
。以下是一个例子:

ReceiverActivity.java 监视名为
“自定义事件名称”
的事件通知的活动

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);
}
使用上述代码,每次单击按钮
R.id.button_send
,就会广播一个意图,并由
ReceiverActivity
中的
mMessageReceiver
接收

调试输出应如下所示:

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! 

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

看到他们的样品了吗

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

compile 'com.google.guava:guava:17.0'

你可以使用弱引用

通过这种方式,您可以自己管理内存,并根据需要添加和删除观察者

当您添加观察者时,添加这些参数-将要添加的活动的上下文强制转换为空接口,添加通知名称,并调用方法来运行接口

运行接口的方法将有一个名为run的函数,用于返回您正在传递的数据,如下所示

public static interface Themethodtorun {
        void run(String notification_name, Object additional_data);
    }
创建一个使用空接口调用引用的观察类。 还可以从addobserver中传递的上下文构造Themethodtorun接口

将观察添加到数据结构中

调用它将是相同的方法,但是您需要做的只是在数据结构中查找特定的通知名称,请使用Themethodtorun.run(通知名称,数据)

这将向您创建具有特定通知名称的观察者的位置发送回调。 别忘了在你完成任务后移除它们

这是弱引用的好参考


我正在将此代码上载到github。睁大眼睛

这里有一些类似于@Shiki-answer的东西,但是从iOS开发者和通知中心的角度来看

首先创建某种通知中心服务:

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);
 }
}
以下是活动中的用法(添加/删除观察员):

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();
    }
}
最后,这里是我们如何通过回调或rest服务或其他方式向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);
}
public void登录服务(最终上下文、字符串用户名、字符串密码){
//做一些异步工作,或者rest调用等。
//...
//在响应时,当我们想要触发并发送作业已完成的通知时
HashMap params=新的HashMap();
参数put(“issucess”,String.valueOf(false));
NotificationCenter.postNotification(上下文、NotificationType.LoginResponse、参数);
}

就这样,干杯

Kotlin:这是一个@Shiki在Kotlin中的版本,在片段中进行了一些重构

  • 在片段中注册观察者
  • Fragment.kt

    class MyFragment : Fragment() {
    
        private var mContext: Context? = null
    
        private val mMessageReceiver = object: BroadcastReceiver() {
            override fun onReceive(context: Context?, intent: Intent?) {
                //Do something here after you get the notification
                myViewModel.reloadData()
            }
        }
    
        override fun onAttach(context: Context) {
            super.onAttach(context)
    
            mContext = context
        }
    
        override fun onStart() {
            super.onStart()
            registerSomeUpdate()
        }
    
        override fun onDestroy() {
            LocalBroadcastManager.getInstance(mContext!!).unregisterReceiver(mMessageReceiver)
            super.onDestroy()
        }
    
        private fun registerSomeUpdate() {
            LocalBroadcastManager.getInstance(mContext!!).registerReceiver(mMessageReceiver, IntentFilter(Constant.NOTIFICATION_SOMETHING_HAPPEN))
        }
    
    }
    
  • 在任何地方发布通知。只有你需要上下文

    LocalBroadcastManager.getInstance(context).sendBroadcast(Intent(Constant.NOTIFICATION_SOMETHING_HAPPEN))```
    
  • PS

  • 您可以像我一样添加常量.kt,以便更好地组织通知。 常数.kt
  • 对于片段中的上下文,可以使用
    activity
    (有时
    null
    )或
    conext
    ,就像我使用的那样

  • 我编写了一个包装器,可以完成同样的工作,相当于使用LiveData的iOS

    包装器:

    class ObserverNotify {
        private val liveData = MutableLiveData<Nothing>()
    
    
        fun postNotification() {
            GlobalScope.launch {
                withContext(Dispatchers.Main) {
                    liveData.value = liveData.value
                }
            }
        }
    
        fun observeForever(observer: () -> Unit) {
            liveData.observeForever { observer() }
        }
    
        fun observe(owner: LifecycleOwner, observer: () -> Unit) {
            liveData.observe(owner) { observer()}
        }
    
    }
    
    class ObserverNotifyWithData<T> {
        private val liveData = MutableLiveData<T>()
    
    
        fun postNotification(data: T) {
            GlobalScope.launch {
                withContext(Dispatchers.Main) {
                    liveData.value = data
                }
            }
        }
    
        fun observeForever(observer: (T) -> Unit) {
            liveData.observeForever { observer(it) }
        }
    
        fun observe(owner: LifecycleOwner, observer: (T) -> Unit) {
            liveData.observe(owner) { observer(it) }
        }
    
    }
    
    通知:

    ObserverCenter.playNextMusic.postNotification()
    ObserverCenter.newFCMTokenDidHandle.postNotification("MyData")
    

    设计要点:BroadcastReceivers和NSNotificationCenter都可以作为事件聚合器运行。与代理或观察者相比的优势在于发送方和接收方是解耦的(它们实际上具有消息或数据耦合,但这是最弱的耦合类型之一)。编辑并更正。非常感谢您花时间编写如此有用的详细响应。您可能不应该在onCreate方法中调用registerReceiver,因为这将泄漏您的活动,并且您的onDestroy方法将永远不会被调用。onResume似乎是调用registerReceiver的更好选择,而onPause则是调用unregisterReceiver的更好选择。与
    NSNotificationCenter
    完全等效的答案应该是公认的!我想指出,使用全局通知可能会导致设计混乱。在跳到下一步之前,考虑一下组件之间的最佳耦合是什么
    LocalBroadcastManager.getInstance(context).sendBroadcast(Intent(Constant.NOTIFICATION_SOMETHING_HAPPEN))```
    
    object Constant {
        const val NOTIFICATION_SOMETHING_HAPPEN = "notification_something_happened_locally"
    }
    
    class ObserverNotify {
        private val liveData = MutableLiveData<Nothing>()
    
    
        fun postNotification() {
            GlobalScope.launch {
                withContext(Dispatchers.Main) {
                    liveData.value = liveData.value
                }
            }
        }
    
        fun observeForever(observer: () -> Unit) {
            liveData.observeForever { observer() }
        }
    
        fun observe(owner: LifecycleOwner, observer: () -> Unit) {
            liveData.observe(owner) { observer()}
        }
    
    }
    
    class ObserverNotifyWithData<T> {
        private val liveData = MutableLiveData<T>()
    
    
        fun postNotification(data: T) {
            GlobalScope.launch {
                withContext(Dispatchers.Main) {
                    liveData.value = data
                }
            }
        }
    
        fun observeForever(observer: (T) -> Unit) {
            liveData.observeForever { observer(it) }
        }
    
        fun observe(owner: LifecycleOwner, observer: (T) -> Unit) {
            liveData.observe(owner) { observer(it) }
        }
    
    }
    
    object ObserverCenter {
        val moveMusicToBeTheNextOne: ObserverNotifyWithData<Music> by lazy { ObserverNotifyWithData() }
        val playNextMusic: ObserverNotify by lazy { ObserverNotify() }
        val newFCMTokenDidHandle: ObserverNotifyWithData<String?> by lazy { ObserverNotifyWithData() }
    }
    
    ObserverCenter.newFCMTokenDidHandle.observe(this) {
        // Do stuff
    }
    
    ObserverCenter.playNextMusic.postNotification()
    ObserverCenter.newFCMTokenDidHandle.postNotification("MyData")