Android Fragments 在两个不同的导航图之间传递数据

tktrz96b  于 2023-05-18  发布在  Android
关注(0)|答案(1)|浏览(109)

我的应用程序中有两个不同的导航图。第一个有3个片段:包含已创建项目列表的片段、创建新项目的片段和包含第二个导航图的支持片段。第二个导航图具有底部导航和包含关于所创建的项目的信息的其他片段。当用户在创建的项目列表中选择其中一个项目时,它将激活。为了存储有关项目的信息,我使用房间数据库。
我真的不明白我怎么能把关于所选项目的数据传递到第二个导航图。
我想用导航图参数传递选定的项目,但由于我想传递此数据的片段在另一个导航图中,我认为我不能使用它。我试着在我的数据库中进行查询,通过id来查找项目,但我真的不知道如何在代码中实现它。
这是我的道:

@Dao
interface ProjectsDao {
    @Insert
    suspend fun addProjects(projects: Projects)
    @Delete
    suspend fun deleteProject(projects: Projects)

    @Query("DELETE FROM projects")
    suspend fun deleteAllProjects()

    @Query("SELECT * FROM projects WHERE projects.id = :id")
    fun findProjectById(id: Int): LiveData<Projects>

    @Update
    suspend fun updateProject(projects: Projects)
    @Query("SELECT * FROM projects")

    fun readAllProjects(): LiveData<List<Projects>>
}

这是我的视图模型(已编辑):

class DataViewModel(application:Application): AndroidViewModel(application) {
     val readAllProjects: LiveData<List<Projects>>
     val currentProject: MutableLiveData<Projects> = MutableLiveData()

    private val repository: ProjectsRepository

    init{
        val projectsDao = ProjectsDatabase.getDatabase(application).projectsDao()
        repository = ProjectsRepository(projectsDao)
        readAllProjects = repository.readAllProjects
    }

    ....

    fun findProjectById(id: Int):LiveData<Projects>{
        return repository.findProjectById(id)
    }
    fun setCurrentItem(projects: Projects) {
        currentProject.value = projects
        //currentProject.postValue(projects)
    }
}

这是我试图通过adapter将MainFragment中所选项目的id传递给导航图SupportFragment中的下一个片段。但是SupportFragment只有FragmentContainerView和底部导航。因此,项数据实际上应该传递给ProjectDetailsFragment

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val currentItem = projectsList[position]
        holder.binding.projectNameTxt.text = currentItem.pr_name

        setListeners(currentItem, holder)
        //holder.binding.rawLayout.setOnClickListener {
        //    val action = MainFragmentDirections.actionMainFragmentToSupportFragment(currentItem)
        //    holder.itemView.findNavController().navigate(action)
        //}
        //holder.binding.deleteProjectID.setOnClickListener{
        //    listener.deleteProject(currentItem)
        //}

    }

    private fun setListeners(currentItem: Projects, holder: MainAdapter.MyViewHolder) {
        holder.binding.rawLayout.setOnClickListener {
            val intent = Intent(holder.itemView.context, SupportFragment::class.java)
            intent.putExtra("id", currentItem.id)
            holder.itemView.context.startActivity(intent)
            //val action = MainFragmentDirections.actionMainFragmentToSupportFragment(intent)
            //holder.itemView.findNavController().navigate(action)
        }
        holder.binding.deleteProjectID.setOnClickListener{
            listener.deleteProject(currentItem)
        }
    }

编辑:这是我的SupportFragment代码

class SupportFragment : Fragment() {
    private val arg by navArgs<SupportFragmentArgs>()
    private var _binding: FragmentSupportBinding? = null
    lateinit var viewModel : DataViewModel
    private val binding get() = _binding!!
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding =  FragmentSupportBinding.inflate(inflater, container, false)
        viewModel = ViewModelProvider(this).get(DataViewModel::class.java)

        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val navHostFragment = childFragmentManager.findFragmentById(R.id.support) as NavHostFragment
        val navController = navHostFragment.findNavController()
        binding.bottomNav.setupWithNavController(navController)
        
        //Setting the current item value
        viewModel.setCurrentItem(arg.currentProject)

}

ProjectDetailsFragment代码

class ProjectDetailsFragment : Fragment() {
    lateinit var viewModel: DataViewModel
    private var _binding: FragmentProjectDetailsBinding? = null
    private val binding get() = _binding!!
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        // Inflate the layout for this fragment
        _binding = FragmentProjectDetailsBinding.inflate(inflater, container, false)
        viewModel = ViewModelProvider(this).get(DataViewModel::class.java)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val setDataObserver = Observer<Projects>{project->
            binding.projectName.text = project.pr_name
        }
        //Observing currentProject
        viewModel.currentProject.observe(viewLifecycleOwner, setDataObserver)

}
ep6jt1vc

ep6jt1vc1#

首先,必须修改setListeners函数以导航到projectsDetailsFragment

private fun setListeners(currentItem: Projects, holder: MainAdapter.MyViewHolder) {
    val action = MainFragmentDirections.actionMainFragmentToProjectDetailsFragment(currentItem.id)
    holder.itemView.findNavController().navigate(action)
}

接下来,在第二个导航图中,确保已为ProjectDetailsFragment定义了目标,并为目标设置了适当的参数
然后在ProjectsDetailsFragment中从参数中获取传递的Id并在数据库查询中使用它:

class ProjectDetailsFragment : Fragment() {
    private val viewModel: DataViewModel by activityViewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val projectId = arguments?.getInt("projectId") ?: 0
        viewModel.findProjectById(projectId).observe(viewLifecycleOwner) { project ->
            // Handle the retrieved project data
        }
    }
}

最后,确保更新viewModel中的findProjectById以返回LiveData对象:

fun findProjectById(id: Int): LiveData<Projects> {
    return repository.findProjectById(id)
}

相关问题