๊ด€๋ฆฌ ๋ฉ”๋‰ด

JiYoung Dev ๐Ÿ–ฅ

[Android] ํฌ์ผ“๋ชฌ ๋„๊ฐ ๋งŒ๋“ค๊ธฐ (Volley, RecyclerView) (2023.07.24~25) ๋ณธ๋ฌธ

full stack/์•ˆ๋“œ๋กœ์ด๋“œ

[Android] ํฌ์ผ“๋ชฌ ๋„๊ฐ ๋งŒ๋“ค๊ธฐ (Volley, RecyclerView) (2023.07.24~25)

Shinjio 2023. 7. 25. 09:36

 

 

 

 

 

 

MainActivity

 

package com.sjy.pokemon

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.android.volley.Request
import com.android.volley.RequestQueue
import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley
import org.json.JSONObject
import java.util.ArrayList


//ViewHolder : ํ•œ๊ฐœ์˜ ์•„์ดํ…œ ๋ทฐ๋ฅผ ๊ตฌ์„ฑ
//Adapter : ViewHolder ์ƒ์„ฑ -> ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ
//MainActivity : Adapter ์ƒ์„ฑ, layout ๊ฒฐ์ •
class MainActivity : AppCompatActivity() {

    lateinit var rcPokemon : RecyclerView
    lateinit var reqQueue : RequestQueue
    var pokemonList = ArrayList<PokemonVO>()

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

        rcPokemon = findViewById(R.id.rcPokemon)
        reqQueue = Volley.newRequestQueue(this@MainActivity)

        //1t์„ธ๋Œ€ ->  151
        for(id in 1 until 152){
            val imgUrl = "https:/raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/$id.png"
            val dataUrl = "https://pokeapi.co/api/v2/pokemon-species/$id"

            val request = object : StringRequest(
                Request.Method.GET,
                dataUrl,
                {
                    response ->
                    val result = JSONObject(response)
                    val name = result.getJSONArray("names").getJSONObject(2).getString("name");
                    val pokemon = PokemonVO(id,imgUrl,name)
                    pokemonList.add(pokemon)

                    val adapter:PokemonAdapter = PokemonAdapter(pokemonList, applicationContext) //์–ด๋Œ‘ํ„ฐ ์ƒ์„ฑ
                    rcPokemon.layoutManager = GridLayoutManager(applicationContext, 2)
                    rcPokemon.adapter = adapter

                },{
                    error ->
                    Log.d("error", error.toString())
                    Toast.makeText(this, "error๋ฐœ์ƒ", Toast.LENGTH_SHORT).show()
                }
            ){} //object ์‚ฌ์šฉ์‹œ body๊ฐ€ ๊ผญ ์žˆ์–ด์•ผ ํ•จ -> {}

            reqQueue.add(request)
        }


    }
}

 

 

VO

 

package com.sjy.pokemon

data class PokemonVO(val pokemonId : Int, val pokemonImgPath : String, val pokemonNm : String)

 

 

ViewHolder

 

package com.sjy.pokemon

import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

class PokemonViewHolder(itemView:View) : RecyclerView.ViewHolder(itemView){

    lateinit var ivPokemon:ImageView
    lateinit var tvPokemon:TextView

    init { //component ์ดˆ๊ธฐํ™”
        ivPokemon = itemView.findViewById(R.id.ivPokemon)
        tvPokemon = itemView.findViewById(R.id.tvPokemon)
    }

}

 

 

Adapter

 

package com.sjy.pokemon

import android.content.Context
import android.content.Intent
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide

class PokemonAdapter(var datas:ArrayList<PokemonVO>, var context:Context) : RecyclerView.Adapter<PokemonViewHolder>(){
    //ViewHolder ์ƒ์„ฑ
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PokemonViewHolder {
        return PokemonViewHolder(
            //View์ƒ์„ฑ
            //attachToRoot : Root(๋ถ€๋ชจ)์—๊ฒŒ ๋ถ™์ผ๊ฑด๋ฐ, ์ƒ์„ฑ ํ›„ ๋ฐ”๋กœ ๋ถ™์ด๋ ค๋ฉด --> true, ์ด๋”ฐ๊ฐ€ ๋ถ™์ด๋ ค๋ฉด --> false
            LayoutInflater.from(parent.context).inflate(R.layout.pokemon_item_view, parent, false)
        )
    }

    //์•„์ดํ…œ(ํฌ์ผ“๋ชฌ) → ViewHolder ๋ฐ”์ธ๋”ฉ
    //๊ฐ€์ง€๊ณ  ์˜ค๋Š” ์•„์ดํ…œ ๊ฐœ์ˆ˜
    override fun getItemCount(): Int {
        return datas.size
    }

    //์•„์ดํ…œ๋“ค์„ ViewHolder์— ๋ฐ”์ธ๋”ฉํ•ด์ฃผ๋Š” ๋ฉ”์„œ๋“œ
    //์•„์ดํ…œ -> ํฌ์ผ“๋ชฌ : pokemonID, pokemonImgPath, pokemon
    override fun onBindViewHolder(holder: PokemonViewHolder, position: Int) {
        val pokemon = datas[position] //ํŠน์ • ์ธ๋ฑ์Šค์— ์žˆ๋Š” ํฌ์ผ“๋ชฌ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ
        //ํฌ์ผ“๋ชฌ ์ด๋ฏธ์ง€ : Glide ๋ผ์ด๋ธŒ๋ฒ„๋ฆฌ -> HTTP ํ†ต์‹ ์„ ํ†ตํ•ด ์ด๋ฏธ์ง€๋ฅผ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
        Glide.with(context).load(pokemon.pokemonImgPath).into(holder.ivPokemon)
        //ํฌ์ผ“๋ชฌ ์ด๋ฆ„
        holder.tvPokemon.text = pokemon.pokemonNm

        holder.itemView.setOnClickListener(){
            //intent ์‚ฌ์šฉ -> DetailActivity๋กœ ์ „ํ™˜
            val intent = Intent(context, DetailActivity::class.java)
            //์•ˆ๋“œ๋กœ์ด๋“œ ์•ฑ์—์„œ ์ƒˆ๋กœ์šด ์•กํ‹ฐ๋น„ํ‹ฐ๊ฐ€ ์‹คํ–‰๋  ๋•Œ๋งˆ๋‹ค
            //๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๋˜ ์•กํ‹ฐ๋น„ํ‹ฐ๋Š” ์Šคํƒ์— ์Œ“์ด๊ฒŒ ๋จ
            //→ ์›ํ•˜์ง€ ์•Š๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋„์ถœ๋  ์ˆ˜ ์žˆ์–ด FLAG๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์กฐ์ • ๊ฐ€๋Šฅ
            //FLAG_ACTIVITY_NEW_TASK : ์ƒˆ๋กœ์šด ์ž‘์—… ์‹œ์ž‘
            //-> ์ผ๋ฐ˜์ ์œผ๋กœ Adapter ๋‚ด์—์„œ startActivity ์‚ฌ์šฉ ์‹œ ์‚ฌ์šฉ
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            //pokemonID -> Int
            //pokemonImgPath -> String
            //pokemonNm -> String
            intent.putExtra("id", pokemon.pokemonId.toInt())
            intent.putExtra("imgUrl", pokemon.pokemonImgPath.toString())
            intent.putExtra("name", pokemon.pokemonNm.toString())
            context.startActivity(intent)
        }

    }
}

 

 

DetailActivity

 

package com.sjy.pokemon

import android.content.Intent
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.ImageView
import android.widget.TableRow
import android.widget.TextView
import androidx.core.view.isVisible
import com.android.volley.Request
import com.android.volley.RequestQueue
import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley
import com.bumptech.glide.Glide
import org.json.JSONObject
import org.w3c.dom.Text

class DetailActivity : AppCompatActivity() {

    lateinit var ivPokemon : ImageView
    lateinit var tvName : TextView
    lateinit var tvType1 : TextView
    lateinit var tvType2 : TextView
    lateinit var tvHeight : TextView
    lateinit var tvWeight : TextView
    lateinit var tblRow : TableRow
    lateinit var reqQueue : RequestQueue

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

        //component ๊ฐ€์ ธ์˜ค๊ธฐ -> ์ด๋ฏธ์ง€, ํ…์ŠคํŠธ
        ivPokemon = findViewById(R.id.ivDetailPokemon)
        tvName = findViewById(R.id.tvPokeName)
        tvType1 = findViewById(R.id.tvType1)
        tvType2 = findViewById(R.id.tvType2)
        tvHeight = findViewById(R.id.tvHeight)
        tvWeight = findViewById(R.id.tvWeight)
        tblRow = findViewById(R.id.tblRow)

        reqQueue = Volley.newRequestQueue(this)

        //intent -> ์ด๋ฆ„, ์ด๋ฏธ์ง€๊ฒฝ๋กœ(Glide), id(์ƒ์„ธ ์ •๋ณด ๊ฐ€์ ธ์˜ฌ ๋•Œ ์‚ฌ์šฉ)
        //์ƒ์„ธ์ •๋ณด url : https://pokeapi.co/api/v2/pokemon/$id
        val intent : Intent = intent
        var id : Int = intent.getIntExtra("id", -1)
        var imgUrl : String? = intent.getStringExtra("imgUrl")
        var name : String? = intent.getStringExtra("name")

        //response -> JSONObject ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ -> result
        //2๋ฒˆ์งธ ํƒ€์ž… ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Œ ! >> ์ฃผ์˜
        //type = result.getJSONArray("types")
        //type.getJSONObject(index).getJSONObject("type").getString("name")
        //                  index -> 0,1 (1๋ฒˆ์งธ ์—†์„ ์ˆ˜ ์žˆ์Œ) ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ• ๊ฑด์ง€ ์ƒ๊ฐ

        //result.getDouble("weight") ๋ฌด๊ฒŒ
        //result.getDouble("height") ํฌ๊ธฐ

        Glide.with(this).load(imgUrl).into(ivPokemon)
        tvName.text = name

        val request = object : StringRequest(
            Request.Method.GET,
            "https://pokeapi.co/api/v2/pokemon/$id",
            {
                response ->
                val result = JSONObject(response)
                val type = result.getJSONArray("types")
                var type1 : String = ""
                var type2 : String = ""

                type1 = type.getJSONObject(0).getJSONObject("type").getString("name")
                if(type.length()==1){
                    tblRow.visibility = View.GONE
                }else{
                    type2 = type.getJSONObject(1).getJSONObject("type").getString("name")
                }

                val weight = result.getDouble("weight")
                val height = result.getDouble("height")

                tvType1.text = type1
                tvType2.text = type2
                tvWeight.text = weight.toString() + "kg"
                tvHeight.text = height.toString() + "m"

                val typeList = HashMap<String, Int>()
                typeList.put("electric", Color.rgb(255,255,102))
                typeList.put("water", Color.rgb(153,255,255))
                typeList.put("fire", Color.rgb(204,0,0))
                typeList.put("grass", Color.rgb(51,255,102))
                typeList.put("poison", Color.rgb(153,0,204))
                typeList.put("bug", Color.rgb(51,102,102))
                typeList.put("ice", Color.rgb(102,204,255))
                typeList.put("ground", Color.rgb(153,102,0))
                typeList.put("rock", Color.rgb(51,51,51))
                typeList.put("normal", Color.rgb(0,0,0))

                typeList.get(type1)?.let { ivPokemon.setBackgroundColor(it) }
            },
            {
                error ->
                Log.d("error", error.toString())
            }
        ){}
        reqQueue.add(request)
    }
}