问题
In my android app, I use firebase cloud messaging to send some data to app.
When the app receives a message through onMessageReceived()
, I check whether a MainActivity
is currently visible (MainActivity
has a static reference to the currently visible MainActivity
), and if the activity is visible, I make some modifications to the activity.
Since onMessageReceived()
is not called in the main thread, I use a Handler
to execute the code in the main thread.
@Override
public void onMessageReceived(final RemoteMessage remoteMessage) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
//Access UI
});
}
Is there anything wrong with this approach? If not, are there any other ways to update the currently visible UI when a cloud message is received?
回答1:
You should avoid writing direct code in the onMessageReceived()
for UI changes in a specific activity. You can channel it through Local broadcast receivers.
When you tend to write code directly in the onMessageReceived()
your FirebaseMessagingService
class will get cluttered. For instance if you have 4 different kind of notification data and each data calls for different activity. Then your code will look something like this :
@Override
public void onMessageReceived(final RemoteMessage remoteMessage) {
if(remoteMessage.getData() != null
&& remoteMessage.getData().containsKey("notification_type")){
switch(remoteMessage.getData().containsKey("notification_type")){
case "type1":
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
//Access UI for some activity
.
.
.
});
break;
case "type2":
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
//Access UI for some activity
.
.
.
});
break;
case "type3":
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
//Access UI for some activity
.
.
.
});
break;
case "type4":
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
//Access UI for some activity
.
.
.
});
break;
}
}
}
Alternatively, if you use local broadcast then your code will be much more modular and organised. Your code will look something like this:
@Override
public void onMessageReceived(final RemoteMessage remoteMessage) {
if(remoteMessage.getData() != null
&& remoteMessage.getData().containsKey("notification_type")){
Intent intent = new Intent();
intent.putExtra("body",messageBody); // Put info that you want to send to the activity
switch(remoteMessage.getData().containsKey("notification_type")){
case "type1":
intent.setAction("ACTION_1") // For activity1
break;
case "type2":
intent.setAction("ACTION_2") //For activity2
break;
case "type3":
intent.setAction("ACTION_3") //For activity3
break;
case "type4":
intent.setAction("ACTION_4") //For activity4
break;
}
sendBroadcast(intent);
}
}
And your activity (eg. activity1) will look something like this: private BroadcastReceiver mReceiver;
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
IntentFilter intentFilter = new IntentFilter(
"ACTION_1"); // Put appropriate action string
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//Get message from intent
String msg_for_me = intent.getStringExtra("some_msg");
//Do your UI Changes stuff here.
}
};
//registering our receiver
this.registerReceiver(mReceiver, intentFilter);
}
@Override
protected void onPause() {
super.onPause();
this.unregisterReceiver(this.mReceiver);//unregister receiver
}
According to me this will help you code your UI changes inside the activity itself and leads you towards a better code management.
Hope it is useful!
来源:https://stackoverflow.com/questions/48035485/firebase-cloud-messaging-accessing-ui-elements-in-onmessagereceived