마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

fusedLocationProviderClient 와 Recyclerview 갱신에 관하여 02

0 추천

fusedlocationProviderClient가 callback 될때 onLocatioResult() 에서 받은 location에서 위경도를 화면에 출력하려고 했습니다. 잘 안되어서 리스너에 달려서 안되나(?) 라고 의심해 버튼에 달아서 버튼을 누르면 출력되도록 해보니 잘 됩니다. 디버그를 찍어봤을때 문제는 adapter의 list가 계속 새로 갱신되는것 같습니다. size 가 1에서 변함이 없습니다. 흠 .. 어디를 더 수정해야할까요? onlocationresult에선 화면 출력을 못하는 것인가요?

하고싶은 코드

val locationRequest = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 1_000L)
            .build()
        val locationCallback = object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult) {
                val new = consoleAdapter.currentList.toMutableList()
                locationResult.lastLocation?.let { location ->
                    // 위치 업데이트 처리
                    Log.d("Location", "Latitude : ${location.latitude}, Longitude : ${location.longitude} , speed : ${location.speed}")

//                    logs.add(Item(info=location.latitude.toString()))
                    new.add(Item(info=location.latitude.toString()))
                }
                consoleAdapter.update(new)

            }

        }
        if (ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.ACCESS_COARSE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            return
        }
        flpc.requestLocationUpdates(locationRequest, locationCallback, null)
버튼으로 확인해본 코드
class MainActivity : AppCompatActivity() {

    private lateinit var console: RecyclerView
    private lateinit var consoleAdapter: PrintAdapter

    var logs = mutableListOf<Item>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


        console = findViewById<RecyclerView>(R.id.items)
        console.layoutManager = LinearLayoutManager(this)
        consoleAdapter = PrintAdapter(this, logs)
        console.adapter = consoleAdapter

        var btn = findViewById<Button>(R.id.btn)
        btn.setOnClickListener(View.OnClickListener {
            var new = consoleAdapter.currentList.toMutableList()
            new.add(Item(info = "1111"))
            consoleAdapter.update(new)
        })
    }


}
class PrintAdapter(
    private val context: Context,
    val items: MutableList<Item>
) : ListAdapter<Item, PrintAdapter.ViewHolder>(diffUtil) {

    companion object {
        val diffUtil = object : DiffUtil.ItemCallback<Item>() {

            override fun areItemsTheSame(oldItem: Item, newItem: Item): Boolean =
                oldItem.id == newItem.id

            override fun areContentsTheSame(oldItem: Item, newItem: Item): Boolean =
                oldItem == newItem

        }
    }

    fun update(rooms: List<Item>) {
        submitList(rooms)
    }

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val info = itemView.findViewById<TextView>(R.id.item)

        fun bind(item: Item) {
            info.text = item.info
        }

    }

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

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(getItem(position))
    }

}

lullulalla (190 포인트) 님이 2월 16일 질문

1개의 답변

+1 추천

먼저 변수 이름을 `new`로 사용하고 계신데 이건 자바의 keyword 이므로 사용하지 않으시는게 좋습니다.

증상을 보면 로케이션 데이터는 업데이트가 되지만 RecyclerView에 보여주는데 문제가 있는 것으로 보이네요. ListAdapter를 사용하셨는데, ListAdapter는 내부적으로 DiffUtil를 사용합니다. RecyclcerView Adpater에 데이터를 제공할 때는, MutableList 보다는 List같은 immutable이 좋습니다. Mutable을 사용하게 되면 Adapter가 실제 데이터가 변경되어도 감지를 못하게 될 가능성있구요, 다른 하나는 어댑터에 사용하는 Item클래스가 hashCode, equals를 제대로 구현했는지와 (data class를 사용하면 자동 구현 해줍니다.) DiffUtil.ItemCallback이 님의 원하는 데이터 표시에 적합한지 체크해 보시기 바랍니다.
 

var new = consoleAdapter.currentList.toMutableList()

 

그리고 위를 보면 데이터를 Adapter에서 가져와서 사용하시는데, 이것보다는 ViewModel/Presenter/Model 같은 곳에서 데이터를 가지고 있고 뷰는 단지 보여주는 역할만 하는 것이 바람직합니다.

spark (227,530 포인트) 님이 2월 18일 답변
...