Assets 폴더에서 로딩한 json 파일 Recyclerview에 표시하기

이번 포스팅에서는 Assets 폴더를 사용하는 법에 대해 알아보겠습니다.

# 안드로이드의 읽기전용 파일 저장폴더

앱을 만들다보면 읽기전용 파일을 앱에 저장하고 불러와서 사용해야 할 때가 있습니다. 이 때 파일은 다음 두 폴더에 저장할 수 있습니다.

  • assets folder
  • resources/raw folder

각 폴더의 특징은 다음과 같습니다.

assets res/raw
파일명 자유롭게 설정 가능 a-z, 0-9, _ 만 사용가능
서브폴더 사용가능 사용불가
파일 리스팅 list()로 가능 불가능
컴파일타임 파일체크 없음 있음
XML에서 접근 불가능 가능
환경별 설정 분리 불가능 가능

간단히 정리하면 XML과 연계하여 다루어야 할 때는 res/raw 폴더를 사용하고, 그렇지 않을 경우 assets 폴더를 사용하면 될 것 같네요.

# 앱 만들어보기

그럼 asset폴더를 사용해보기 위해 json 파일을 불러와서 Recyclerview에 표시하는 간단한 앱을 만들어 보겠습니다.

Recyclerview는 RecyclerView에 View Binding 적용하기에서 작성했던 프로젝트를 참고해서 사용하겠습니다. Json 포맷을 다루어야 하므로 우선 Gson 라이브러리를 추가합니다. Gson에 대한 구체적인 설명에 대해서는 SharedPreferences를 json 포맷으로 관리하기에서 설명한 내용을 참조하시기 바랍니다.

# 데이터 준비

New > Folder > Asset Folder를 선택하여 assets 폴더를 추가합니다.

데이터는 경기데이터드림에서 제공하는 코로나바이러스 감염증 선별진료소 운영 의료기관 현황데이터를 사용하겠습니다.

sheet 탭에서 json을 클릭하여 데이터를 다운받습니다. 다운받아보면 내용이 한줄에 모여있어 보기 불편합니다. 사용하는데는 관계 없지만 값들을 정렬하는게 보기에 좋을 것 같으니 Json Formatter 에서 파일을 정렬하고 data.json이라는 파일명을 붙여 assets 폴더에 저장합니다.

# 데이터클래스 준비

데이터 파일에는 데이터기준일자, 시군명, 의료기관명, 의료기관 구분, 의료기관 전화번호1, 의료기관 전화번호2, 소재지지번주소, 소재지도로명주소, WGS84위도, WGS84경도 등 여러가지 탭이 있습니다.

각 데이터는 배열 속의 데이터클래스로 관리하기 위해 데이터클래스를 만들어줍니다. 데이터클래스의 특징에 대해서는 Data class 이해하고 RecyclerView에서 사용하기강의에서 설명한 내용을 참고하시기 바랍니다.

안드로이드 스튜디오에 Kotlin data class File from JSON 플러그인을 설치하면 json 파일을 손쉽게 데이터클래스로 변환할 수 있습니다. 플러그인을 설치한 뒤 New > Kotlin data class File from JSON을 선택하여 위에서 만든 json 데이터와 클래스명을 입력하면 자동으로 데이터클래스와, 그 클래스를 아이템으로 갖는 배열 클래스가 생성되는데 클래스 이름은 CoronaMed라고 하겠습니다.

# Recyclerview 구축하기

다음으로 새로 만들어진 데이터클래스의 형식에 맞게 Recyclerview와 ViewHolder의 형태를 정의해줍니다. activity_main.xml에 RecyclerView를 추가합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical"
        tools:listitem="@layout/list_item"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

list_item.xml 파일을 만들어서 ViewHolder를 구성합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingStart="24dp"
        android:paddingEnd="16dp"
        android:text="Name"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/tv_type"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingStart="32dp"
        android:paddingEnd="16dp"
        android:text="type"
        android:textSize="18sp" />

    <TextView
        android:id="@+id/tv_phonenum"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingStart="32dp"
        android:paddingEnd="16dp"
        android:text="phonenum"
        android:textSize="18sp" />

    <TextView
        android:id="@+id/tv_address"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingStart="32dp"
        android:paddingEnd="16dp"
        android:text="address"
        android:textSize="18sp" />

</LinearLayout>

그리고 마지막으로 Recyclerview 어댑터를 작성합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class MyRecyclerViewAdapter(private val dataset: CoronaMed) :
    RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder>() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val binding = ListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return MyViewHolder(binding)
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        holder.bind(dataset[position])
    }

    override fun getItemCount(): Int {
        return dataset.size
    }

    class MyViewHolder(private val binding: ListItemBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(data: CoronaMedItem) {
            with(binding) {
                tvName.text = data.mEDINSTNM
                tvType.text = data.dISTRCTDIVDTLS
                tvPhonenum.text = data.eMGCCENTERTELNO
                tvAddress.text = data.rEFINEROADNMADDR
            }
        }
    }
}

# assets 폴더속 파일 불러오기

다음은 메인액티비티에서 assets 폴더속 파일을 불러오기 위한 함수를 만들어줍니다. assets 폴더에 접근하기 위해 Asset Manager 인스턴스를 생성하고 open 메소드로 파일을 오픈합니다.그리고 bufferedReader를 이용해 InputStream을 텍스트로 변환합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
private fun getJsonData(filename: String): CoronaMed? {
    val assetManager = resources.assets
    var result: CoronaMed? = null
    try {
        val inputStream = assetManager.open(filename)
        val reader = inputStream.bufferedReader()
        val gson = Gson()
        result = gson.fromJson(reader, CoronaMed::class.java)
    } catch (e:IOException) {
        e.printStackTrace()
    }
    return result
}

나머지는 이렇게 얻어온 CoronaMed 객체를 Recyclerview 어댑터에 전달해주면 됩니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(binding.root)

    val testdata = getJsonData("data.json")

    binding.recyclerView.apply {
        layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
        adapter = MyRecyclerViewAdapter(testdata!!)
        addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL))
    }
}

이렇게 해서 assets 폴더에서 json 파일을 불러오는 법에 대해 알아보았습니다.

Built with Hugo
Theme Stack designed by Jimmy