0

I have this function to update my ImageView in my android project

    private fun weatherImageSetup(currentWeather: CurrentWeather) {
        fun setImage(imageId: Int) {
            viewBinding.weatherStatusImg.setImageDrawable(
                ContextCompat.getDrawable(requireContext(), imageId)
            )
        }
        fun partOfDay(day: Int, night: Int) = if (viewModel.currentDateTime.toInt() in 6..18) {
            day
        } else {
            night
        }
        when (currentWeather.weather[0].id.toString()[0]) {
            '2' -> {
                setImage(R.drawable.thunderstorm_img)
            }
            '3' -> {
                val imageId: Int = partOfDay(R.drawable.drizzle_day_img, R.drawable.drizzle_night_img)
                setImage(imageId)
            }
            '5' -> {
                val imageId: Int = partOfDay(R.drawable.rainy_day_img, R.drawable.rainy_night_img)
                setImage(imageId)
            }
            '6' -> {
                val imageId: Int = partOfDay(R.drawable.snow_day_img, R.drawable.snow_night_img)
                setImage(imageId)
            }
            '7' -> {
                val imageId: Int = if (currentWeather.weather[0].id == 781) {
                    R.drawable.tornado_img
                } else {
                    R.drawable.fog_img
                }
                setImage(imageId)
            }
            '8' -> {
                val imageId: Int = if (currentWeather.weather[0].id == 800) {
                    partOfDay(R.drawable.clear_day_sky_img, R.drawable.clear_night_sky_img)
                } else {
                    partOfDay(R.drawable.cloud_day_img, R.drawable.cloud_night_img)
                }
                setImage(imageId)
            }
        }
    }

I have to use this function in two places in my project. The first one is in my fragment to update the ImageView, and the second one is in the RecyclerView adapter to update the ImageView in the RecyclerView. However, when I implemented it, the IDE showed me a warning of "duplicate code fragment". I wonder how to fix this warning because I use this function in two separate classes and in two separate files.

Warning image

HaBuiDuc
  • 19
  • 6

2 Answers2

1

The first way would to put this into a Class. Since it has view references though, this is a very bad approach (unless you keep the setView outside of it). The second, and what I'd go for, is to make this an extension function:

fun CurrentWeather.getImage(): Int {
val currentWeatherId: Int = this.weather[0].id
val currentTime = Calendar.getInstance().get(Calendar.HOUR_OF_DAY)
fun isDay() = currentTime in 6..18
return when (currentWeatherId.toString()[0]) {
    '2' -> R.drawable.thunderstorm_img
    '3' -> if (isDay()) R.drawable.drizzle_day_img else R.drawable.drizzle_night_img
    '5' -> if (isDay()) R.drawable.rainy_day_img else R.drawable.rainy_night_img
    '6' -> if (isDay()) R.drawable.snow_day_img else R.drawable.snow_night_img
    '7' -> if (currentWeatherId == 781) R.drawable.tornado_img else R.drawable.fog_img
    '8' -> if (currentWeatherId == 800) {
        if (isDay()) R.drawable.clear_day_sky_img else R.drawable.clear_night_sky_img)
    } else {
        if (isDay()) R.drawable.cloud_day_img else R.drawable.cloud_night_img)
    }
    else -> R.drawable.unknown
 }
}

Then to set the view you keep the same method you have:

viewBinding.weatherStatusImg.setImageDrawable(
    ContextCompat.getDrawable(requireContext(), currentWeather.getImage)
)
Eliza Camber
  • 1,536
  • 1
  • 13
  • 21
  • Where should I create an extension function? If I create an extension function in a fragment, can I use this function in an adapter or do I have to create it in both classes? I have never worked with extension functions before. – HaBuiDuc Jun 27 '23 at 12:29
  • Most of the times I create a separate file (X.kt) and I put all my extension functions there (not in a class). Some prefer to put them at the same file as the object (CurrentWeather). Then you can use it from anywhere you like by just calling it as the example above. – Eliza Camber Jun 27 '23 at 13:47
  • You can have it as a function inside the class. It's a matter of preference and the result will be the same. Either you put this as an extension function in a new file, or you put it as a normal funtion inside your CurrentWeather class the result is the same, and the code is not duplicated. In any case, you're not extending the classes; you only extend (if you decide so) the CurrentWeather data class – Eliza Camber Jun 27 '23 at 14:14
0

I have not much experience with android but can you implement one public class with this (public) function and then to use this class when needing? Maybe to use a "static" function. You can pass variables as parameters if you need it.

DimisV
  • 11
  • 4
  • Thank you but is there any better way to do that because i think one class just for update ImageView is so complicated and hard to maintain – HaBuiDuc Jun 27 '23 at 10:25
  • So, maybe the other solution is better. – DimisV Jun 27 '23 at 10:50
  • 1
    I can not comment at the other answer, check if you can use extesion function for both classes (it seems you can not) https://kotlinlang.org/docs/extensions.html – DimisV Jun 27 '23 at 13:12
  • https://stackoverflow.com/questions/70739459/how-to-create-an-extension-function-with-multiple-receivers-in-kotlin – DimisV Jun 27 '23 at 13:26
  • Thank you very much! Your answer helped me a lot – HaBuiDuc Jun 27 '23 at 14:06