code

NSNotificationCenter와 동등한 Android

codestyles 2020. 9. 4. 07:27
반응형

NSNotificationCenter와 동등한 Android


아이폰 애플리케이션을 안드로이드로 포팅하는 과정에서 앱 내에서 소통하는 가장 좋은 방법을 찾고 있습니다. 인 텐트가가는 길인 것 같습니다. 이것이 최선의 (유일한) 옵션입니까? NSUserDefaults는 성능과 코딩 모두에서 Intents보다 훨씬 가벼운 무게로 보입니다.

또한 상태에 대한 애플리케이션 하위 클래스가 있지만 다른 활동에서 이벤트를 인식하도록해야합니다.


이것을 시도해 볼 수 있습니다 : http://developer.android.com/reference/java/util/Observer.html


내가 찾은 가장 좋은 것은 Android 지원 패키지의 일부인 LocalBroadcastManager 입니다 .

LocalBroadcastManager 문서에서 :

프로세스 내의 로컬 개체에 인 텐트 브로드 캐스트를 등록하고 전송하는 도우미입니다. 이것은 sendBroadcast (Intent)를 사용하여 글로벌 브로드 캐스트를 보내는 것보다 많은 이점이 있습니다.

  • 브로드 캐스팅중인 데이터가 앱을 떠나지 않을 것임을 알고 있으므로 개인 데이터 유출에 대해 걱정할 필요가 없습니다.
  • 다른 애플리케이션이 이러한 브로드 캐스트를 앱에 보낼 수 없으므로 악용 할 수있는 보안 허점에 대해 걱정할 필요가 없습니다.
  • 시스템을 통해 글로벌 브로드 캐스트를 보내는 것보다 더 효율적입니다.

이것을 사용할 때 an IntentNSNotification. 다음은 예입니다.

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();
}

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);
}

With the code above, every time the button R.id.button_send is clicked, an Intent is broadcasted and is received by mMessageReceiver in ReceiverActivity.

The debug output should look like this:

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! 

Here is something similar to @Shiki answer, but from the angle of iOS developers and Notification center.

First create some kind of NotificationCenter service:

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);
 }
}

Then, you will also need some enum type to be secure of mistakes in coding with strings - (NotificationType):

public enum NotificationType {

   LoginResponse;
   // Others

}

Here is usage(add/remove observers) for example in activities:

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();
    }
}

and here is finally how we post notification to NotificationCenter from some callback or rest service or whatever:

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);
}

that's it, cheers!


You could use this: http://developer.android.com/reference/android/content/BroadcastReceiver.html, which gives a similar behavior.

You can register receivers programmatically through Context.registerReceiver(BroadcastReceiver, IntentFilter) and it will capture intents sent through Context.sendBroadcast(Intent).

Note, though, that a receiver will not get notifications if its activity (context) has been paused.


I found that the usage of EventBus of Guava lib is the simplest way for publish-subscribe-style communication between components without requiring the components to explicitly register with one another

see their sample on 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") );
} 

you can add this lib simply on Android Studio by adding a dependency to your build.gradle:

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

You could use weak references.

This way you could manage the memory yourself and add and remove observers as you please.

When you addObserver add these parameters - cast that context from the activity you are adding it in to the empty interface, add a notification name, and call the method to run interface.

The method to run interface would have a function that is called run to return the data that you are passing something like this

public static interface Themethodtorun {
        void run(String notification_name, Object additional_data);
    }

Create a observation class that invokes a reference with a empty interface. Also construct your Themethodtorun interface from the context being passed in the addobserver.

Add the observation to a data structure.

To call it would be the same method however all you need to do is find the specific notification name in the data structure, use the Themethodtorun.run(notification_name, data).

This will send a callback to where ever you created an observer with a specific notification name. Dont forget to remove them when your done!

This is good reference for weak references.

http://learningviacode.blogspot.co.nz/2014/02/weak-references-in-java.html

I am in the process of uploading this code to github. Keep eyes open!

참고URL : https://stackoverflow.com/questions/3947641/android-equivalent-to-nsnotificationcenter

반응형