【问题标题】:How to only call a function once in a fragment android kotlin如何在片段android kotlin中只调用一次函数
【发布时间】:2021-04-14 13:28:16
【问题描述】:

当我的应用程序启动时,我调用一个使用 retrofit/gson 的函数并调用一个 rest API,然后从那里将数据发送到适配器并放置在回收器视图中。我遇到的问题是,当我导航到另一个片段并再次返回时,再次调用该函数,但旧数据保留在回收器视图中,导致当我只在回收器视图中存在相同数据的多个副本时希望它调用一次或至少在回收器视图中只有一组数据

我尝试从活动而不是片段调用函数,将函数放入 onCreate 方法和数学 if-else 表达式都不会产生预期的效果。

我的代码:

MainFragment.kt

class MainFragment : Fragment() {
    
    private var text1list = mutableListOf<String>()
    private var text2list = mutableListOf<String>()
    private var text3list = mutableListOf<String>()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_main, container, false)
        view.see_codes.setOnClickListener {
            findNavController().navigate(R.id.action_mainFragment_to_listFragment2)
        }

        TestGet()


        return view
    }

    val BASE_URL = "https://run.mocky.io/v3/"

    private fun TestGet() {

            val api = Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()
                    .create(SimpleApi::class.java)

            GlobalScope.launch(Dispatchers.IO) {
                val response = api.phonehome()

                try {
                    for (Mlist in response.Mlist){
                        Log.d("MainActivity", "Result + $Mlist")
                        addToList(Mlist.text1, Mlist.text2, Mlist.text3)
                    }

                    withContext(Dispatchers.Main){
                        setUpRecyclerView()
                    }
                }catch (e: Exception){
                    println("you messed up the connection some how")
                }
            }
    }


    
    private fun setUpRecyclerView() {
        main_recyclerview.layoutManager = LinearLayoutManager(this.context)
        main_recyclerview.adapter = MainAdapter(text1list,text2list,text3list)
    }

    private fun addToList(text1: String, text2: String, text3: String){
        text1list.add(text1)
        text2list.add(text2)
        text3list.add(text3)

    }
}

我的适配器

MainAdapter.kt
class MainAdapter(
        private var text1: List<String>, private var text2: List<String>, private var text3: List<String>)  : RecyclerView.Adapter<MainAdapter.ViewHolder>() {

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
        var itemtext1 : TextView = itemView.findViewById(R.id.note_text_view_1)
        var itemtext2 : TextView = itemView.findViewById(R.id.note_text_view_2)
        var itmetext3 : TextView = itemView.findViewById(R.id.note_text_View_3)

    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainAdapter.ViewHolder {
        val v = LayoutInflater.from(parent.context).inflate(R.layout.carditem,parent,false)
        return ViewHolder(v)
    }

    override fun getItemCount(): Int {
        return text1.size
    }

    override fun onBindViewHolder(holder: MainAdapter.ViewHolder, position: Int) {
        holder.itemtext1.text = text1[position]
        holder.itemtext2.text = text2[position]
        holder.itmetext3.text = text3[position]
    }

}

感谢您的宝贵时间。

【问题讨论】:

    标签: java android kotlin android-recyclerview retrofit


    【解决方案1】:

    您可以查看 RecyclerView.adapter 是否为空。并采取相应的行动。

    如果不是null,你已经查询并设置了适配器。

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_main, container, false)
        view.see_codes.setOnClickListener {
            findNavController().navigate(R.id.action_mainFragment_to_listFragment2)
        }
    
        if (view.main_recyclerview.adapter == null) {
            TestGet()
        }
    
        return view
    }
    

    如果问题只是 RecyclerView 中的重复数据,那么您可以在setUpRecyclerView() 函数中检查适配器是否为空。

    private fun setUpRecyclerView() {
        if (main_recyclerview.adapter == null) {  
            main_recyclerview.layoutManager = LinearLayoutManager(this.context)
            main_recyclerview.adapter = MainAdapter(text1list,text2list,text3list)
        }
    }
    

    编辑:

    作为最后的手段,您可以创建一个名为 extensions 或其他名称的单独 kotlin 文件,并在其中包含一个对象,如下所示:

    object Settings{
        var recViewAlreadyUpdated : Boolean = false
    }
    

    此变量在应用程序运行时创建,只要应用程序存在,您就可以使用此标志将数据加载到您的 RecyclerView 中,如下所示:

    if (!Settings.recViewAlreadyUpdated) {
        TestGet()
        Settings.recViewAlreadyUpdated = true
    }
    

    【讨论】:

    • 虽然这里的概念似乎是正确的想法,但从 OP 的代码中很难判断该解决方案是否有效。这个问题不包括main_recyclerview 是如何声明或初始化的,所以我们不知道它是否会为空。我们可能需要更深入地挖掘一个级别并检查回收器视图是否具有适配器。
    • 对不起我的错。编辑了答案。您需要从正在加载到片段的视图中获取 recView 引用。立即尝试
    • 对不起 mehran,但代码不起作用,它会使应用程序崩溃。它说: java.lang.NullPointerException: main_recyclerview 在 com.notifiyr.fragments.main.MainFragment.onCreateView(MainFragment.kt:50) 不能为空,谢谢
    • 不是fragment_mainxml文件中的recyclerView吗?
    • @MehranB 感谢您的帮助,我能够弄明白
    【解决方案2】:

    我认为这里的正确方法是只创建RecyclerView 并且它是Adapter 一次。然后更新适配器存储的数据并调用notifyDataChanged()

    【讨论】:

    • 这让我很感兴趣。请详细说明,我以前使用过“notifyDataChanged()”,但在这里我不能让它工作。
    【解决方案3】:

    我相信我发现我的应用出了什么问题,但首先非常感谢 Mehran B,是他为这个解决方案奠定了基础。

    问题在于代码顶部的mutableListOf 变量。他们持有上一次调用函数的数据,只是添加到它们中。所以首先我试图通过清除所有mutableListOf 的数据来解决这个问题。好吧,我不知道该怎么做,但如果有人知道怎么做,请发表评论。

    所以我最终做的是这个

        if (!Settings.recViewAlreadyUpdated) {
            TestGet()
    
            Settings.recViewAlreadyUpdated = true
    
        }else{
            text1list = mutableListOf()
            text2list = mutableListOf()
            text3list = mutableListOf()
            TestGet()
        }
    

    如果以前没有使用过该函数,我所做的就是overite 或创建一个新的mutableListOf(我不确定是哪个)。再次感谢 Mehran B https://stackoverflow.com/users/10695663/mehran-b

    【讨论】:

    • 不用担心。我很高兴能帮上忙
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-19
    • 2021-04-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多