Android Primary/Detail Flow 模板的 fragment 点击跳转逻辑

文章目录

    TODO

    • 看懂原有 primary/detail 模板的跳转逻辑
    • 新建 snippet

    list fragment

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        val itemDetailFragmentContainer: View? = view.findViewById(R.id.item_detail_nav_container)
        setupRecyclerView(recyclerView, itemDetailFragmentContainer)
    }
    
    private fun setupRecyclerView(
        recyclerView: RecyclerView,
        itemDetailFragmentContainer: View?
    ) {
        recyclerView.adapter = SimpleItemRecyclerViewAdapter(
            PlaceholderContent.ITEMS, itemDetailFragmentContainer
        )
    }
    

    但是这个 item_detail_nav_container 只存在于 sw600dp 的 layout 文件中:

    > grep item_detail_nav_container -r app/
    app/src/main/res/layout-sw600dp/fragment_item_list.xml:        android:id="@+id/item_detail_nav_container"
    

    为何在手机上运行不报错呢?

    recycler view adapter

    class SimpleItemRecyclerViewAdapter(
            private val values: List<PlaceholderContent.PlaceholderItem>,
            private val itemDetailFragmentContainer: View?
    ) :
        RecyclerView.Adapter<SimpleItemRecyclerViewAdapter.ViewHolder>() {
        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            val item = values[position]
            holder.idView.text = item.id
            holder.contentView.text = item.content
    
            with(holder.itemView) {
                tag = item
                setOnClickListener { itemView ->
                    val item = itemView.tag as PlaceholderContent.PlaceholderItem
                    // Bundle: A mapping from String keys to various Parcelable values.
                    // A Bundle is very much like a Java Map object that maps String keys to values.
                    // The reason Android doesn't use plain old Map objects for this is that Map is too flexible;
                    // it can contain objects (such as, say, I/O streams) that cannot be serialized.
                    // The Bundle API restricts the types of objects that can be added to a bundle
                    // in such a way that the bundle's contents are guaranteed to be serializable.
                    // The Android framework relies on this property.
                    val bundle = Bundle()
                    bundle.putString(
                        ItemDetailFragment.ARG_ITEM_ID,
                        item.id
                    )
                    if (itemDetailFragmentContainer != null) {
                        itemDetailFragmentContainer.findNavController()
                            .navigate(R.id.fragment_item_detail, bundle)
                    } else {
                        // 为何不都使用这个逻辑呢?
                        // 实际测试也确实没有问题
                        itemView.findNavController().navigate(R.id.show_item_detail, bundle)
                    }
                }
                ...
            }
        }
    }
    

    show_item_detail 的定义:

    > grep show_item_detail -r app/
    app/src/main/res/navigation/primary_details_nav_graph.xml:            android:id="@+id/show_item_detail"
    
    <fragment
        android:id="@+id/item_list_fragment"
        android:name="com.sunzhongwei.ble.ItemListFragment"
        android:label="ItemListFragment">
        <action
            android:id="@+id/show_item_detail"
            app:destination="@id/item_detail_fragment" />
    </fragment>
    

    detail fragment

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        // public final android.os.Bundle getArguments()
        // Return the arguments supplied when the fragment was instantiated, if any.
        arguments?.let {
            if (it.containsKey(ARG_ITEM_ID)) {
                // Load the placeholder content specified by the fragment
                // arguments. In a real-world scenario, use a Loader
                // to load content from a content provider.
                item = PlaceholderContent.ITEM_MAP[it.getString(ARG_ITEM_ID)]
            }
        }
    }
    

    activity

    override fun onCreate(savedInstanceState: Bundle?) {
        val navHostFragment =
            supportFragmentManager.findFragmentById(R.id.nav_host_fragment_item_detail) as NavHostFragment
        val navController = navHostFragment.navController
        appBarConfiguration = AppBarConfiguration(navController.graph)
        setupActionBarWithNavController(navController, appBarConfiguration)
    }
    

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式