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

问题描述 投票:3回答:2

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

我希望如果用户在聊天片段上点击主页按钮,然后点击通知,它应该在最后一个状态启动,不要调用活动的onDestroy然后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);
        }
    }
}

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

如何避免app创建qazxsw poi和qazxsw poi?

java android firebase android-fragments push-notification
2个回答
2
投票

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

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

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

我想推荐的另一件好事是使用CursorLoader。你可能会发现LoaderCallbacks解释了实现。 ViewModel幸存于Activity,您可以使用documentation here保存实例状态,这将减少加载时间。

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


2
投票

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

我会在活动首次创建时在活动标记下的清单文件中添加onDestroy。它可以帮助我避免在Activity中重新创建Fragment。

onCreate
© www.soinside.com 2019 - 2024. All rights reserved.