아이폰 애플리케이션을 안드로이드로 포팅하는 과정에서 앱 내에서 소통하는 가장 좋은 방법을 찾고 있습니다. 인 텐트가가는 길인 것 같습니다. 이것이 최선의 (유일한) 옵션입니까? NSUserDefaults는 성능과 코딩 모두에서 Intents보다 훨씬 가볍습니다.
또한 상태에 대한 애플리케이션 하위 클래스가 있지만 다른 활동에서 이벤트를 인식하도록해야합니다.
답변:
이것을 시도해 볼 수 있습니다 : http://developer.android.com/reference/java/util/Observer.html
내가 찾은 가장 좋은 것은 Android 지원 패키지의 일부인 LocalBroadcastManager 입니다 .
LocalBroadcastManager 문서에서 :
프로세스 내의 로컬 개체에 인 텐트 브로드 캐스트를 등록하고 전송하는 도우미입니다. 이것은 sendBroadcast (Intent)를 사용하여 글로벌 브로드 캐스트를 보내는 것보다 많은 이점이 있습니다.
- 브로드 캐스팅중인 데이터가 앱을 떠나지 않을 것임을 알고 있으므로 개인 데이터 유출에 대해 걱정할 필요가 없습니다.
- 다른 애플리케이션이 이러한 브로드 캐스트를 앱에 보낼 수 없으므로 악용 할 수있는 보안 허점에 대해 걱정할 필요가 없습니다.
- 시스템을 통해 글로벌 브로드 캐스트를 보내는 것보다 더 효율적입니다.
이것을 사용할 때 an Intent
은 NSNotification
. 다음은 예입니다.
라는 이벤트에 대한 알림을 감시하는 활동입니다 "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();
}
알림을 보내거나 브로드 캐스트하는 두 번째 활동입니다.
@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
클릭, 텐트를 방송하고 수신한다 mMessageReceiver
에서 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!
NSNotificationCenter
답이 허용되어야합니다!
다음은 @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);
}
}
그런 다음 문자열로 코딩 할 때 실수를 방지하기 위해 일부 열거 형 유형 (NotificationType)도 필요합니다.
public enum NotificationType {
LoginResponse;
// Others
}
예를 들어 활동에서 사용 (관찰자 추가 / 제거)은 다음과 같습니다.
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();
}
}
마지막으로 콜백 또는 휴식 서비스 등에서 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);
}
그게 다야, 건배!
Bundle params
대신 사용 하는 HashMap
것이 다른 유형의 매개 변수를 전달하는 데 더 편리 하다는 것을 알았습니다 . 이 사이 좋은 연결은 Intent
과 Bundle
:intent.putExtras(params)
비슷한 동작을 제공하는 http://developer.android.com/reference/android/content/BroadcastReceiver.html을 사용할 수 있습니다 .
Context.registerReceiver (BroadcastReceiver, IntentFilter)를 통해 프로그래밍 방식으로 수신자를 등록 할 수 있으며 Context.sendBroadcast (Intent)를 통해 전송 된 인 텐트를 캡처합니다.
하지만 수신자는 활동 (컨텍스트)이 일시 중지 된 경우 알림을받지 않습니다.
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") );
}
build.gradle에 종속성을 추가하여 Android Studio에서 간단히이 lib를 추가 할 수 있습니다.
compile 'com.google.guava:guava:17.0'
Kotlin : 조각에서 약간의 리팩터링이있는 Kotlin의 @Shiki 버전이 있습니다.
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))```
추신 :
object Constant {
const val NOTIFICATION_SOMETHING_HAPPEN = "notification_something_happened_locally"
}
activity
(때로는 null
) 사용하거나 conext
내가 사용한 것과 비슷할 수 있습니다 .약한 참조를 사용할 수 있습니다.
이렇게하면 메모리를 직접 관리하고 원하는대로 관찰자를 추가 및 제거 할 수 있습니다.
addObserver가 이러한 매개 변수를 추가 할 때-추가하려는 활동에서 해당 컨텍스트를 빈 인터페이스에 캐스트하고 알림 이름을 추가하고 인터페이스를 실행하는 메소드를 호출하십시오.
인터페이스를 실행하는 메소드에는 다음과 같이 전달하는 데이터를 반환하기 위해 run이라는 함수가 있습니다.
public static interface Themethodtorun {
void run(String notification_name, Object additional_data);
}
빈 인터페이스로 참조를 호출하는 관찰 클래스를 만듭니다. 또한 addobserver에서 전달되는 컨텍스트에서 Themethodtorun 인터페이스를 구성하십시오.
데이터 구조에 관찰을 추가합니다.
이를 호출하려면 동일한 방법이지만 데이터 구조에서 특정 알림 이름을 찾기 만하면됩니다. Themethodtorun.run (notification_name, data)을 사용하세요.
이렇게하면 특정 알림 이름으로 관찰자를 생성 한 위치로 콜백이 전송됩니다. 완료되면 제거하는 것을 잊지 마십시오!
이것은 약한 참조에 대한 좋은 참조입니다.
http://learningviacode.blogspot.co.nz/2014/02/weak-references-in-java.html
이 코드를 github에 업로드하는 중입니다. 계속 눈을 뜨십시오!