单击通知时启动片段而不会丢失状态



我有聊天应用程序,也可以通过通知单击直接启动。聊天片段也会通过在应用程序内单击手动启动。

我希望如果用户在聊天片段上点击主页按钮,然后单击通知,它应该在最后一个状态下启动,并且不调用活动的onDestroy然后onCreate

像这样Activity通过通知启动Fragment

((AppCompatActivity)context).getFragmentManager().beginTransaction().replace(R.id.Navigation_Main_Layout, screenFragment,"Chat").commit();

我正在处理来自FirebaseMessagingService的通知

public class FireBase_Messaging_Service extends FirebaseMessagingService {
public static final String TAG="###FireBase MSG###";
public static final int NOTIFICATION=5;
String UserName;
String ID;
String Msg;
Map<String,String> data;
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Log.d(TAG,"From "+remoteMessage.getFrom());
if (remoteMessage.getData().size()>0){
data = remoteMessage.getData();
Log.d(TAG,"Message Data "+remoteMessage.getData());
data = remoteMessage.getData();
UserName = data.get("name");
ID = data.get("ID");
Msg = data.get("Message");
showNotification(Msg,ID,UserName);
}
if (remoteMessage.getNotification()!=null){
Log.d(TAG,"Message Notification Body "+remoteMessage.getNotification().getBody());
// Toast.makeText(this, "Notification "+remoteMessage.getNotification().getBody(), Toast.LENGTH_LONG).show();
}
}
private void showNotification(String Message,String ID,String UserName) {
Log.d(TAG,"Show Notification "+Message+" "+ID);
Intent intent=new Intent(this, Navigation_Drawer.class);
intent.putExtra("Type","Text");
//intent.putExtra("Type",MsgType);
intent.putExtra("ID",ID);
intent.putExtra("uname",UserName);
intent.putExtra("Message",Msg);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent=PendingIntent.getActivity(this,NOTIFICATION,intent,PendingIntent.FLAG_UPDATE_CURRENT);
int color = getResources().getColor(R.color.black);
String ChannelID = "Message";
notificationChannel(ChannelID,"Chat");
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(),ChannelID)
.setSmallIcon(R.drawable.default_x)
.setColor(color)
.setContentTitle(UserName)
.setContentText(Message)
.setChannelId(ChannelID)
.setTicker("My App")
.setDefaults(Notification.DEFAULT_VIBRATE | Notification.DEFAULT_SOUND | Notification.FLAG_SHOW_LIGHTS)
.setLights(0xff00ff00, 1000, 500) // To change Light Colors
.setStyle(new NotificationCompat.BigTextStyle().bigText(Message))//For Expandable View
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(this);
managerCompat.notify(NOTIFICATION,builder.build());
}
@Override
public void onDeletedMessages() {
super.onDeletedMessages();
}
private void notificationChannel (String ChannelID, String channelName) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel  channel = new NotificationChannel(ChannelID,channelName, NotificationManager.IMPORTANCE_DEFAULT);
channel.setLightColor(Color.GREEN);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
}
}
}

在上面的代码中,我尝试使用不同的标志Intent,例如Intent.FLAG_ACTIVITY_NEW_TASK,IntentFLAG_ACTIVITY_SINGLE_TOPFLAG_ACTIVITY_BROUGHT_TO_FRONTFLAG_ACTIVITY_CLEAR_TOP等。但是,它总是先调用活动的(导航抽屉(onDestroy,然后再调用onCreate。然后它从头开始启动片段。

如何避免应用程序重新创建ActivityFragment

据我所知,Android 活动的预期行为与活动和片段的 Android 生命周期相冲突。当用户按下"后退"或"主页"按钮时,活动或片段将按照该活动或片段实例的生命周期进行onPauseonDestroy。除非您在活动中调用避免活动中的finish,否则无法避免它,该onDestroy函数调用。但是,您不希望完成该活动,而是希望使用相同的活动,并且不希望重新创建该活动。

所以我在想一种不同的方法来解决你的问题。大多数情况下,重新创建活动或片段的问题直接指示要获取的资源,并且在初始化活动或片段时要获取的大量资源是开销。因此,当资源在保存的实例状态下已经可用时,我们可能会避免获取要在活动或片段中使用的资源。

例如,当您在活动的onCreate函数中获取保存在 SQLite 数据库中的某些数据时,您可能不希望在活动的方向更改时再次获取这些数据,这会强制重新创建活动。在这种情况下,您可能需要选择一个加载器(我说的是实现LoaderCallbacksCursorLoader(,它可以在活动重新创建中幸存下来。如果已经获取数据,则使用加载程序的实现将不会再次从 SQLite 数据库获取数据,并将在重新创建活动时提供数据。

我想推荐的另一件美丽的事情是 使用ViewModel.您可以在此处找到解释实现的文档。ViewModel活动重新创建中幸存下来,您可以使用ViewModel保存实例状态,这将减少加载时间。

重点是,您可能无法欺骗生命周期功能,但您可以选择使用数据模型,这些数据模型将在活动和片段的重新创建中幸存下来。

我在第一次启动时加载活动和片段,没有任何标志。当我收到通知时,我正在添加一个标志,该标志使活动首先调用onDestroy然后onCreate

每当活动首次创建时,我都会在活动标签下的清单文件中添加android:launchMode="singleTask"。它可以帮助我避免在活动中重新创建片段。

<activity
android:name=".Navigation_Drawer"
android:launchMode="singleTask"
android:theme="@style/AppTheme"/>

最新更新