MVVM 中 RecyclerView 中的分页重复值

Pagination Duplicating Values in RecyclerView in MVVM

我也是 Kotlin MVVM 的新手,我尝试使用传统方法实现分页,但我的 RecyclerView 遇到了问题,每当我滚动它时,数据就会重复,我尝试了 DiffUtils,但没有帮助。

我在 VIEWMODEL 中记录了数据 class 数据没有重复 但是,当我登录 Activity 时,我观察到它显示重复值

SEARCHRESULTACTIVITY.KT

class SearchResultActivity : AppCompatActivity() {
private lateinit var layoutManager: LinearLayoutManager
private lateinit var recyclerView: RecyclerView
private lateinit var pullAdapter: CustomAdapter
private var pageNumber = 1
private var totalItemsCount = 0
private var firstVisibleItemsCount = 0
private var visibleItemsCount = 0
private var previousTotal = 0
private var loading = true
private var fillPullList: ArrayList<RepoPull> = ArrayList()
private var userName: String = ""
private var repoName: String = ""
private var isEnd = false


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    initialize()

    getDataPull(userName, repoName)

    loadNextData()

}

private fun initialize() {
    setContentView(R.layout.activity_search_result)
    recyclerView = findViewById(R.id.repoRecView)
    layoutManager = LinearLayoutManager(this)

    getSearchQuery()

}

private fun getSearchQuery() {
    userName = intent.getStringExtra("owner").toString()
    repoName = intent.getStringExtra("repo").toString()
    populatePullRv()

}

private fun populatePullRv() {
    recyclerView.addItemDecoration(DividerItemDecoration(this, DividerItemDecoration.VERTICAL))
    recyclerView.layoutManager = layoutManager
    pullAdapter = CustomAdapter(this, fillPullList)
    recyclerView.adapter = pullAdapter
    progressBar.visibility = View.VISIBLE
}

private fun loadNextData() {
    recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {

        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            super.onScrolled(recyclerView, dx, dy)

            val mLayoutManger = recyclerView.layoutManager as LinearLayoutManager
            visibleItemsCount = mLayoutManger.childCount
            totalItemsCount = mLayoutManger.itemCount
            firstVisibleItemsCount = mLayoutManger.findFirstVisibleItemPosition()

            if (loading) {
                if (totalItemsCount > previousTotal) {
                    previousTotal = totalItemsCount
                    pageNumber++
                    loading = false
                    progressBar.visibility = View.GONE
                }
            }
            if (!loading && (firstVisibleItemsCount + visibleItemsCount) >= totalItemsCount) {
                getDataPull(userName, repoName)
                loading = true
                Log.d("PAGE", pageNumber.toString())
            }


        }

    })
}

private fun getDataPull(username: String?, reponame: String?) {
    val myViewModel = ViewModelProviders.of(this).get(PullVM::class.java)

    myViewModel.endofList.observe(this, {
        if (it == true) {
            isEnd = true
            progressBar.visibility = View.GONE
            Toast.makeText(this@SearchResultActivity, "All PR Fetched", Toast.LENGTH_SHORT)
                .show()

        }

    })

    myViewModel.status.observe(this, {
        if (it == false) {
            showError(getString(R.string.no_net))

        }
    })

    myViewModel.getPullDataFromVM().observe(this, {

        if (it != null) {
           listRepos(it)  **//DUPLICATE VALUE COMING**
        } else {

            showError(getString(R.string.nothing_found))
        }
    })



    myViewModel.getPullList(username.toString(), reponame.toString(), pageNumber)

}

private fun showError(s: String) {
    progressBar.visibility = View.GONE
    val theView =
        this@SearchResultActivity.findViewById<View>(android.R.id.content)
    Snackbar.make(
        theView,
        s,
        Snackbar.LENGTH_LONG
    ).show()
}


@SuppressLint("NotifyDataSetChanged")
fun listRepos(repos: List<RepoPull>) {
    if (!isEnd) {
        progressBar.visibility = View.GONE
        fillPullList.addAll(repos)
        pullAdapter.notifyDataSetChanged()
    }
}}

PULLVM(查看模型).kt

 class PullVM : ViewModel() {
var pullList: MutableLiveData<List<RepoPull>>
var status = MutableLiveData<Boolean?>()
var endofList = MutableLiveData<Boolean?>()

init {

    pullList = MutableLiveData()
}

fun getPullDataFromVM(): MutableLiveData<List<RepoPull>> {

    return pullList
}

fun getPullList(ownerName: String, repoName: String, pgNo: Int) {

    val retriever = GitHubRetriever


    val callback = object : Callback<List<RepoPull>> {
        override fun onFailure(call: Call<List<RepoPull>>, t: Throwable) {
            status.value = false
        }

        override fun onResponse(
            call: Call<List<RepoPull>>,
            response: Response<List<RepoPull>>
        ) {
            if (response.body()?.size == 0) {
                endofList.value = true
            }
            if (response.code() == 404) {
                pullList.postValue(null)

            } else {
                status.value = true
                val repos = response.body()
                if (repos != null) {
                    pullList.postValue(repos) 
                }
            }
        }

    }

    retriever.userRepos(
        callback,
        ownerName,
        repoName,
        pgNo
    )
}

尝试将您的 viewModel 实例化和观察者设置移动到 onCreate,这样您就不必创建新的 viewModel 实例并为您的 LiveDatas 设置新的可观察对象。

将 myViewModel 声明为 Activity 的 lateinit 属性 并将此部分移至 onCreate

myViewModel = ViewModelProviders.of(this).get(PullVM::class.java)

    myViewModel.endofList.observe(this, {
        if (it == true) {
            isEnd = true
            progressBar.visibility = View.GONE
            Toast.makeText(this@SearchResultActivity, "All PR Fetched", Toast.LENGTH_SHORT)
                .show()

        }

    })

    myViewModel.status.observe(this, {
        if (it == false) {
            showError(getString(R.string.no_net))

        }
    })

    myViewModel.getPullDataFromVM().observe(this, {

        if (it != null) {
           listRepos(it)  **//DUPLICATE VALUE COMING**
        } else {

            showError(getString(R.string.nothing_found))
        }
    })

private fun getDataPull(username: String?, reponame: String?)

应该只包含

myViewModel.getPullList(username.toString(), reponame.toString(), pageNumber)