android-fragments 尝试更改起始片段会导致导航抽屉出现故障

zphenhs4  于 2022-11-13  发布在  Android
关注(0)|答案(1)|浏览(147)

我很难理解我做错了什么,所以我希望你能帮助我。

内容:

我正在使用Android Studio构建一个Android应用程序,以控制和监控我家中的物联网设备。我从Navigation Drawer Activity示例开始,因此我有3个片段和一个导航抽屉:

主页片段(“Accueil”):出现第一个片段,其中包含两个用于创建通知的测试按钮
**运动片段(“监视摄像机”)
:显示摄像机流网络视图的片段
**** Jmeter 板片段(“表格边框”)
*:显示另一个web视图片段

Navigation drawer
Home fragment
我目前正在使用一个通知,该通知会直接打开我的应用进入Motion片段。为此,我使用了一个额外的通知发送的pendingIntent。根据它的值,在MainActivity的 onCreate 函数中,navController会被强制显示所请求的片段。在我的情况下,我希望通知显示Motion片段(“Camera de surveillance”)。
Notification

Intent intent = getIntent();
String fragmentName = intent.getStringExtra(FRAGMENTNAME);
if (fragmentName == null) fragmentName = "";
switch (fragmentName) {
    case "motion":
        navController.navigate(R.id.nav_motion);
        break;
    case "dashboard":
        navController.navigate(R.id.nav_dashboard);
        break;
    case "home":
    default:
        navController.navigate(R.id.nav_home);
        break;
}

那么接下来,测试:我打开我的应用程序,点击测试按钮“按钮1”以显示通知,关闭我的应用程序,点击通知,宾果!Motion片段首先打开!这工作得很完美...至少我是这么想的。

问题:

通过这样做,我得到了一个奇怪的行为时,应用程序已经从通知打开:我无法到达家园碎片。
在导航抽屉中,点击“Accueil”菜单打开Home片段,打开Motion片段(“Camera de surveillance”)。要查看Home片段,我需要退出应用程序并再次打开它。
我猜想,单击导航抽屉上的“Accueil”按钮以显示Home片段会重置MainActivity并调用 onCreate 函数,但这对我来说没有意义,因为该函数是创建应用程序时的第一个回调函数,而不是之后调用的,对吗?有人知道实际发生了什么吗?我如何才能获得所需的行为?

**编辑:**经过一些调试,使用通知作为指示器,我发现MainActivity的onCreate函数在启动时只被调用一次。此外,当导航抽屉处于“怪异行为”状态时,单击“返回”导航按钮将返回Home片段,并纠正导航抽屉的“怪异行为”。

我用来改变第一个片段的函数是导航控制器中的“navigate”函数,它将Home片段中的函数保存在内存中(真正的第一个显示的片段),我导航到了Motion片段。因此,只要我没有通过按“Back”按钮返回导航回栈,它就会在内存中保存以下内容:当我单击Home片段时,我导航到Motion片段。
我需要找到一种方法来删除导航历史记录,或者找到另一种方法来在开始时显示Motion片段。

完整文件源:

MainActivity.java

public class MainActivity extends AppCompatActivity {
    public static final String FRAGMENTNAME = "com.mrxana91dev.maisonpaul.fragmentstartname";

    public NotificationManagerCompat notificationManagerCompat;

    private AppBarConfiguration mAppBarConfiguration;
    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        setSupportActionBar(binding.appBarMain.toolbar);
        binding.appBarMain.fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
        DrawerLayout drawer = binding.drawerLayout;
        NavigationView navigationView = binding.navView;
        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        mAppBarConfiguration = new AppBarConfiguration.Builder(
                R.id.nav_home, R.id.nav_motion, R.id.nav_dashboard)
                .setOpenableLayout(drawer)
                .build();
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
        NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
        NavigationUI.setupWithNavController(navigationView, navController);

        this.notificationManagerCompat = NotificationManagerCompat.from(this);

        // ADDED CODE TO CHANGE FIRST FRAGMENT DEPENDING ON FRAGMENTNAME EXTRA
        Intent intent = getIntent();
        String fragmentName = intent.getStringExtra(FRAGMENTNAME);
        if (fragmentName == null) fragmentName = "";
        switch (fragmentName) {
            case "motion":
                navController.navigate(R.id.nav_motion);
                break;
            case "dashboard":
                navController.navigate(R.id.nav_dashboard);
                break;
            case "home":
            default:
                navController.navigate(R.id.nav_home);
                break;
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onSupportNavigateUp() {
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
        return NavigationUI.navigateUp(navController, mAppBarConfiguration)
                || super.onSupportNavigateUp();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle item selection
        switch (item.getItemId()) {
            case R.id.action_settings:
                Intent intent = new Intent(this, SettingsActivity.class);
                startActivity(intent);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
}

家庭片段.java

public class HomeFragment extends Fragment {
    public static final String EXTRA_FRAGMENT = "com.mrxana91dev.maisonpaul.fragmentstartname";

    private FragmentHomeBinding binding;

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        HomeViewModel homeViewModel =
                new ViewModelProvider(this).get(HomeViewModel.class);

        binding = FragmentHomeBinding.inflate(inflater, container, false);
        View root = binding.getRoot();

        final TextView textView = binding.textHome;
        final TextView textView2 = binding.textView2;
        homeViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);
        homeViewModel.getText2().observe(getViewLifecycleOwner(), textView2::setText);

        final Button testButton1 = binding.testButton1;
        final Button testButton2 = binding.testButton2;
        testButton1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendOnChannel1();
            }
        });
        testButton2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendOnChannel2();
            }
        });
        return root;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }

    private void sendOnChannel1()  {
        String title = "Maison Paul - Test notification";
        String message = "Mouvement repéré !";

        MainActivity mainActivity = (MainActivity) getActivity();

        Intent intent = new Intent(mainActivity, MainActivity.class);
        intent.putExtra(EXTRA_FRAGMENT, "motion");
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(mainActivity, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE);

        Notification notification = new NotificationCompat.Builder(mainActivity, NotificationApp.CHANNEL_1_ID)
                .setSmallIcon(R.drawable.ic_baseline_home_24)
                .setContentTitle(title)
                .setContentText(message)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setCategory(NotificationCompat.CATEGORY_MESSAGE)
                .setContentIntent(pendingIntent)
                .setAutoCancel(true)
                .build();

        int notificationId = 1;
        mainActivity.notificationManagerCompat.notify(notificationId, notification);
    }

    private void sendOnChannel2()  {
        String title = "Maison Paul - Test notification";
        String message = "Notification from channel 2 !";

        MainActivity mainActivity = (MainActivity) getActivity();

        Notification notification = new NotificationCompat.Builder(mainActivity, NotificationApp.CHANNEL_2_ID)
                .setSmallIcon(R.drawable.ic_menu_camera)
                .setContentTitle(title)
                .setContentText(message)
                .setPriority(NotificationCompat.PRIORITY_LOW)
                .setCategory(NotificationCompat.CATEGORY_PROMO) // Promotion.
                .build();

        int notificationId = 2;
        mainActivity.notificationManagerCompat.notify(notificationId, notification);
    }
}
js81xvg6

js81xvg61#

好吧!我知道了。
我必须通过创建两个操作来更改导航菜单(mobile_navigation. xml)中的一些内容:

  • 一个从Home片段导航到Motion片段
  • 一个从Home片段导航到Dashboard片段的组件

这两个动作都是使用popUpTo和popUpToInclusive设置的。

移动的导航.xml(提取)

<action
    android:id="@+id/action_nav_home_to_nav_dashboard"
    app:destination="@id/nav_dashboard"
    app:launchSingleTop="false"
    app:popUpTo="@id/nav_home"
    app:popUpToInclusive="true" />

然后,我使用相应的操作,而不是直接使用导航片段的id作为“navigate”函数的参数。

主活动.java -创建时(提取)

Intent intent = getIntent();
        String fragmentName = intent.getStringExtra(FRAGMENTNAME);
        if (fragmentName == null) fragmentName = "";
        switch (fragmentName) {
            case "motion":
                navController.navigate(R.id.action_nav_home_to_nav_motion);
                break;
            case "dashboard":
                navController.navigate(R.id.action_nav_home_to_nav_dashboard);
                break;
            case "home":
            default:
                // No action needed requesting the Home fragment as it's already the starting fragment
                break;
        }

在所有这些更改之后,单击通知仍会按预期显示Motion片段,而单击导航抽屉中的“Accueil”按钮会按预期显示Home片段。
解决了!

相关问题