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

时间:2018-06-15 20:53:56

标签: java android firebase android-fragments push-notification

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

我想如果用户在聊天片段上点击主页按钮,然后点击通知,它应该在最后一个状态启动,不要调用活动onDestroy然后{{1} }。

通过onCreate这样的通知启动Fragment

Activity

我正在处理来自((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); } } } ,例如IntentIntent.FLAG_ACTIVITY_NEW_TASK,IntentFLAG_ACTIVITY_SINGLE_TOPFLAG_ACTIVITY_BROUGHT_TO_FRONT等。但是,它总是调用活动&#39; s(导航抽屉)FLAG_ACTIVITY_CLEAR_TOP首先然后onDestroy。然后它从开始启动片段。

如何避免应用重新制作onCreateActivity

2 个答案:

答案 0 :(得分:2)

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

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

例如,当您在活动的onCreate函数中获取保存在SQLite数据库中的某些数据时,您可能不希望在活动的方向更改时再次获取它,这会强制重新创建活动。在这种情况下,您可能需要选择一个加载器(我正在讨论CursorLoaderLoaderCallbacks的实现),它在Activity重新生成后仍然存在。如果已经获取,则使用加载器的实现将不会再从SQLite数据库获取数据,并将在重新创建活动时提供数据。

我想推荐的另一件好事是使用ViewModel。您可能会发现documentation here解释实现。 ViewModel在活动重新生存中存活,您可以使用ViewModel保存实例状态,这将减少加载时间。

重点是,您可能无法欺骗生命周期功能,但您可能会选择使用数据模型,这些数据模型将在重新创建活动和片段后继续存在。

答案 1 :(得分:2)

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

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

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