전화이력 관련 목록 표시에서 20개를 표시하고 스크롤 시에 추가적으로 20개씩 더 조회하여 화면에 표시하는 기능

class Fragment1() : Fragment() {
    private var searchIndex = 0
    private var loadingState = false
    private var list = ArrayList<ListData>()
    private lateinit var listAdapter:AdapterList
 
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        InitList()
 
        val view = inflater.inflate(R.layout.fragment_list, container, false)
        // RecyclerView Set the adapter
        if (view is RecyclerView) {
            listAdapter = AdapterList(list)
            view.setOnScrollChangeListener {v, scrollX, scrollY, oldScrollX, oldScrollY ->
                var layoutManager:LinearLayoutManager = (view.layoutManager as LinearLayoutManager)
                if(!loadingState) {
                    // 20개 중 마지막 5개가 남았을 쯤 20개를 다시 조회
                    if(layoutManager != null && layoutManager.findLastCompletelyVisibleItemPosition() == list.size - 5) {
                        loadingState = true
                        loadList()
                    }
                    loadingState = false
                }
            }
        }
        return view
    }
 
    fun InitList() {
        searchIndex = 0;
        getList(searchIndex)
    }
 
    fun loadList() {
        getList(searchIndex)
        listAdapter.notifyDataSetChanged()
    }
 
    fun getList(index:Int) {
        if(requireActivity() == null) {
            return
        }
 
        // SQLite의 order by 이후에 ROWNUM 효과를 위한 구문
        val afterOrderBy = "date DESC LIMIT ${index + 20} OFFSET $index"
 
        /**
        SELECT    date, transcription, photo_id, subscription_component_name, call_screening_app_name, type, geocoded_location, presentation, duration, subscription_id, is_read, number,
        features, voicemail_uri, normalized_number, via_number, matched_number, last_modified, new, numberlabel, lookup_uri, data4, photo_uri, data3, data2, data1, data_usage,
        phone_account_address, formatted_number, add_for_all_users, block_reason, numbertype, call_screening_component_name, countryiso, name, post_dial_digits, transcription_state, _id
        FROM (SELECT * FROM calls WHERE logtype IN (100, 110, 150, 500, 800, 900, 950, 1000, 1050, 1100, 1150, 1350, 1400, 1450, 1500) ORDER BY date DESC ) calls
        ORDER BY date DESC LIMIT 20 OFFSET 0
         */
        val cursor = requireActivity().contentResolver.query(CallLog.Calls.CONTENT_URI, null, null, null, afterOrderBy)
        val numberIndex = cursor?.getColumnIndex(CallLog.Calls.NUMBER)
        val typeIndex = cursor?.getColumnIndex(CallLog.Calls.TYPE)
        val dateIndex = cursor?.getColumnIndex(CallLog.Calls.DATE)
        val durationIndex = cursor?.getColumnIndex(CallLog.Calls.DURATION)
 
        while(cursor?.moveToNext() == true) {
            val date = Date(cursor.getString(dateIndex!!).toLong())
            val number = cursor.getString(numberIndex!!)
            val type = cursor.getString(typeIndex!!).toInt()
            val duration = cursor.getString(durationIndex!!).toLong()
 
            list.add(
                ListData(
                    date,
                    number,
                    type,
                    duration
                )
            )
        }
        cursor?.close()
        searchIndex += 20
    }
}

참고 사이트 :

https://yujin-dev.tistory.com/35

구현예제 :

https://github.com/jaydenkim465/PhoneCallProject