Java 如何在片段中只调用函数一次android kotlin

Java 如何在片段中只调用函数一次android kotlin,java,android,kotlin,android-recyclerview,retrofit,Java,Android,Kotlin,Android Recyclerview,Retrofit,当我的应用程序启动时,我调用一个使用翻新/gson的函数,并调用一个restapi,然后从那里将数据发送到适配器并放置在回收器视图中。我遇到的问题是,当我导航到另一个片段并再次返回时,会再次调用该函数,但旧数据仍保留在recycler视图中,这导致在我只希望它调用一次或在recycler视图中至少只有一组数据时,相同数据的多个副本位于recycler视图中 我尝试了从活动而不是片段调用函数,将函数放入onCreate方法和数学if-else表达式中,但都没有产生预期的效果 我的代码: MainF

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

我尝试了从活动而不是片段调用函数,将函数放入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)

    }
}
MainFragment.kt
类MainFragment:Fragment(){
private var text1list=mutableListOf()
private var text2list=mutableListOf()
私有变量text3list=mutableListOf()
覆盖创建视图(
充气器:布局充气器,容器:视图组?,
savedInstanceState:捆绑?
):查看{
val视图=充气机。充气(R.layout.fragment_main,容器,错误)
view.see_codes.setOnClickListener{
findNavController().导航(R.id.action\u main fragment\u到\u listFragment2)
}
TestGet()
返回视图
}
val BASE_URL=”https://run.mocky.io/v3/"
私人娱乐测试获取(){
val api=reformation.Builder()
.baseUrl(基本URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(SimpleApi::class.java)
GlobalScope.launch(Dispatchers.IO){
val response=api.phonehome()
试一试{
for(响应中的Mlist.Mlist){
Log.d(“主活动”,“结果+$Mlist”)
addToList(Mlist.text1、Mlist.text2、Mlist.text3)
}
withContext(Dispatchers.Main){
setUpRecyclerView()
}
}捕获(e:例外){
println(“你怎么搞砸了连接”)
}
}
}
私人娱乐设置回收视图(){
main\u recyclerview.layoutManager=LinearLayoutManager(this.context)
main_recyclerview.adapter=main适配器(text1列表、text2列表、text3列表)
}
私人娱乐添加列表(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]
    }

}
maintadapter.kt
类主适配器(
private-var text1:List,private-var text2:List,private-var text3:List):RecyclerView.Adapter(){
内部类ViewHolder(itemView:View):RecyclerView.ViewHolder(itemView){
var itemtext1:TextView=itemView.findViewById(R.id.note\u text\u view\u 1)
var itemtext2:TextView=itemView.findViewById(R.id.note\u text\u view\u 2)
var itmetext3:TextView=itemView.findViewById(R.id.note\u text\u View\u 3)
}
重写CreateViewHolder(父级:ViewGroup,viewType:Int):MainAdapter.ViewHolder{
val v=LayoutFlater.from(parent.context)。充气(R.layout.carditem,parent,false)
返回视窗支架(v)
}
重写getItemCount():Int{
返回text1.size
}
覆盖BindViewHolder(支架:MainAdapter.ViewHolder,位置:Int){
holder.itemtext1.text=text1[位置]
holder.itemtext2.text=text2[位置]
holder.itmetext3.text=text3[位置]
}
}

感谢您抽出时间。

您可以检查并查看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)
    }
}
编辑: 作为最后手段,您可以创建一个名为
扩展名
的单独kotlin文件或其他文件,其中包含一个对象,如下所示:

object Settings{
    var recViewAlreadyUpdated : Boolean = false
}
此变量是在应用程序运行时创建的,只要应用程序存在,您就可以使用此标志将数据加载到您的RecyclerView中,如下所示:

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

我认为正确的方法是只创建
RecyclerView
,它是
Adapter
一次。然后你更新adapater存储的数据并调用
notifyDataChanged()

我相信我已经找到了我的应用程序的问题所在,但首先要感谢Mehran B,是他为这个解决方案奠定了基础

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

所以我最终做的是

    if (!Settings.recViewAlreadyUpdated) {
        TestGet()

        Settings.recViewAlreadyUpdated = true

    }else{
        text1list = mutableListOf()
        text2list = mutableListOf()
        text3list = mutableListOf()
        TestGet()
    }

我所做的是重写或创建一个新的
mutableListOf
(我不确定是哪个),如果这个函数以前没有使用过的话。再次感谢Mehran B

虽然这里的概念似乎是正确的,但很难从OP的代码中判断这个解决方案是否有效。问题不包括如何声明或初始化
main\u recyclerview
,因此我们不知道它是否会为null。我们可能需要更深一层,检查回收器视图是否有适配器。对不起,我的错。编辑了答案。您需要从正在加载片段的视图中获取recView引用。立即尝试抱歉,mehran,但是代码不起作用,它会使应用程序崩溃。它说:java.lang.NullPointerException:com.notifiyr.fragments.main.MainFragment.onCreateView(main