【JetPack】Navigation知识点总结

1、Navigation Graph:

一种新的XML资源文件,包含应用程序所有的页面,以及页面间的关系。

复制代码
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/my_nav_graph"
    app:startDestination="@id/homeFragment">

    <fragment
        android:id="@+id/homeFragment"
        android:name="com.example.navigation.HomeFragment"
        android:label="fragment_home"
        tools:layout="@layout/fragment_home" >
        <action
            android:id="@+id/action_homeFragment_to_detailFragment"
            app:destination="@id/detailFragment" />
    </fragment>
    <fragment
        android:id="@+id/detailFragment"
        android:name="com.example.navigation.DetailFragment"
        android:label="fragment_detail"
        tools:layout="@layout/fragment_detail" >
        <action
            android:id="@+id/action_detailFragment_to_homeFragment"
            app:destination="@id/homeFragment" />
    </fragment>
</navigation>

2、NavHostFragment:

一个特殊的Fragment,可以将它看作是其他Fragment的容器,Navigation Graph中的Fragment正是通过NavHostFragment进行展示的。

复制代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragmentContainerView"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="409dp"
        android:layout_height="729dp"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/my_nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>

3、NavController:

用于在代码中完成Navigation Graph中具体的页面切换工作。

复制代码
MainActivity.java
public class MainActivity extends AppCompatActivity {
    NavController navController;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
		// 这样写会报错
    	// NavController navController = Navigation.findNavController(this, R.id.fragmentContainerView);
        // 需要先通过id获取到对应的NavHostFragment容器
        NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentContainerView);
        if (navHostFragment != null) {
       		 // 如果不为空,再获取到的容器对应的NavController
            navController = navHostFragment.getNavController();
        } else {
            throw new RuntimeException("NavHostFragment not found");
        }
        // 该代码的主要目的是将 ActionBar(或 Toolbar)与 NavController 关联起来,以便在使用 Android 导航组件时,ActionBar 可以自动更新其显示内容
        NavigationUI.setupActionBarWithNavController(this, navController);
    }
    
    @Override
    public boolean onSupportNavigateUp() {
        // header上返回按键好用
        return navController.navigateUp();
    }
}
HomeFragment.java
@Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Button button = getView().findViewById(R.id.button);
        button.setOnClickListener(view -> {
        	// 由于最外层设置了NavController,所以这里可以通过容器中的view找到NavController
            NavController navController = Navigation.findNavController(view);
            // 通过NavController进行导航,确定目的地
            navController.navigate(R.id.action_homeFragment_to_detailFragment);
        });
    }
DetailFragment.java
@Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Button button = getView().findViewById(R.id.button2);
        button.setOnClickListener((v)->{
            // 由于最外层设置了NavController,所以这里可以通过容器中的view找到NavController
            NavController navController = Navigation.findNavController(v);
            // 通过NavController进行导航,确定目的地
            navController.navigate(R.id.action_detailFragment_to_homeFragment);
        });
    }

三者之间的关系

当你想切换Fragment时,使用NavController对象,告诉它你想要去Nlavigation Graph中的哪个Fragment,NavController会将你想去的Fragment展示NavHostFragment中
实现顺序

1.创建Fragment

2.创建navgation_graph,指定fragment切换逻辑

3.在Activity的页面中添加navHostFragmrnt容器进行界面显示

4.在Activity中通过navHostFragmrnt获取到navController,并设置bar和fragment的对应关系,以及bar上返回按键生效

5.在需要触发fragment切换的位置通过获取navController进行导航,设置对应的action,确认触发后目的地
添加页面切换动画

页面之间参数传递

方法一:直接传递bundle对象(接收数据时需要知道对应key值以及value类型,并且需要判空)

复制代码
        Bundle bundle = new Bundle();
        bundle.putString("user_name", "Jay");
        NavController navController = Navigation.findNavController(view);
        navController.navigate(R.id.action_homeFragment_to_detailFragment, bundle);

接收bundle对象

复制代码
		Bundle arguments = getArguments();
		String userName = null;
		if (arguments != null) {
		    userName = arguments.getString("user_name");
		    Log.d("userName", "" + userName);
		}

方法二:引入arg插件

复制代码
		dependencies {
		    // 添加 safe-arg 插件依赖
		    classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.4.0")
		}
		plugins {
		    id 'androidx.navigation.safeargs'
		}

        Bundle bundle = new HomeFragmentArgs.Builder()
                .setUserName("Jay")
                .setAge(20)
                .build().toBundle();
  
        HomeFragmentArgs args = HomeFragmentArgs.fromBundle(getArguments());
        String username = args.getUserName();
        int age = args.getAge();
        Log.d("Test", "userName = " + userName + "age = " + age);

NavigationUI的使用场景

Fragment切换时,设计到AppBar上的内容显示,为了方便统一管理引入NavigationUI

复制代码
public class MainActivity extends AppCompatActivity {
    private NavController navController;
    private AppBarConfiguration appBarConfiguration;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentContainerView);
        if (navHostFragment != null) {
            navController = navHostFragment.getNavController();
        }
        appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
        // 将Appbar与Navigation建立联系
        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.menu_settings, menu);
        return true;
    }
    // 响应Meun的点击事件
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        return NavigationUI.onNavDestinationSelected(item, navController) || super.onOptionsItemSelected(item);
    }
    // 响应AppBar的返回按键
    @Override
    public boolean onSupportNavigateUp() {
        return NavigationUI.navigateUp(navController, appBarConfiguration) || super.onSupportNavigateUp();
    }
}

跳转后的假面不显示meun

复制代码
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        setHasOptionsMenu(true);
        return inflater.inflate(R.layout.fragment_setting, container, false);
    }

    @Override
    public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
        menu.clear();
        super.onCreateOptionsMenu(menu, inflater);
    }

监听页面切换完成的回调

复制代码
        // 监听界面切换完成
        navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
            @Override
            public void onDestinationChanged(@NonNull NavController navController, @NonNull NavDestination navDestination, @Nullable Bundle bundle) {
                Log.d("test","onDestinationChanged");
            }
        });

深层链接DeepLink之PendingIntent

复制代码
private void sendNotifycation() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel myChannel = new NotificationChannel(getActivity().getPackageName(), "MyChannel", NotificationManager.IMPORTANCE_DEFAULT);
            myChannel.setDescription("My NotificationChannel");
            NotificationManager notificationManager = getActivity().getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(myChannel);
        }

        NotificationCompat.Builder builder = new NotificationCompat.Builder(getActivity(), getActivity().getPackageName())
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setContentTitle("Deep Link")
                .setContentText("点我")
                .setPriority(NotificationManager.IMPORTANCE_DEFAULT)
                .setContentIntent(getPendingIntent());
        // 发送通知
        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getActivity());

        if (ActivityCompat.checkSelfPermission(getActivity(), android.Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        notificationManager.notify(notifyId++, builder.build());
    }

    private PendingIntent getPendingIntent() {
        Bundle bundle = new Bundle();
        bundle.putString("name","Jay");
        return Navigation.findNavController(getActivity(),R.id.button)
                .createDeepLink()
                .setGraph(R.navigation.my_nav_graph)
                .setDestination(R.id.detailFragment)
                .setArguments(bundle)
                .createPendingIntent();
    }

深层链接DeepLink之Url

相关推荐
sun0077008 小时前
android ndk编译valgrind
android
AI视觉网奇10 小时前
android studio 断点无效
android·ide·android studio
jiaxi的天空10 小时前
android studio gradle 访问不了
android·ide·android studio
No Silver Bullet11 小时前
android组包时会把从maven私服获取的包下载到本地吗
android
catchadmin11 小时前
PHP serialize 序列化完全指南
android·开发语言·php
tangweiguo0305198712 小时前
Kable使用指南:Android BLE开发的现代化解决方案
android·kotlin
00后程序员张14 小时前
iOS App 混淆与资源保护:iOS配置文件加密、ipa文件安全、代码与多媒体资源防护全流程指南
android·安全·ios·小程序·uni-app·cocoa·iphone
柳岸风16 小时前
Android Studio Meerkat | 2024.3.1 Gradle Tasks不展示
android·ide·android studio
编程乐学16 小时前
安卓原创--基于 Android 开发的菜单管理系统
android
whatever who cares18 小时前
android中ViewModel 和 onSaveInstanceState 的最佳使用方法
android