코딩 일기장/Android(Kotlin)

[안드로이드]Python(Django) <=> MySQL <=> Json(2)

minWachya 2021. 5. 1. 15:46
반응형

이제 json 형태의 데이터를 안드로이드에서 가져와서 아래처럼 보여지도록 만들어 보겠다.

결과 화면


 

1) AndroidManifest.xml에서 인터넷 접근 위한 권한 설정하기

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

 

웹으로부터 데이터 통신하기 위해

application에도

android:usesCleartextTraffic="true" 추가

 

리사이클러 뷰 사용하기 위한 플러그인 추가하고 sync now해준다.

plugins

id 'kotlin-android-extensions'


2) gradle(:app) 설정

외부 서버에서 데이터 불러와야하는데

안드로이드에서는 외부서버 접근할 수 없어서

gradle(:app)의 dependencise에

implementation 'com.squareup.retrofit2:retrofit:2.3.0' 추가

json 쉽게 다루기 위해
implementation 'com.squareup.retrofit2:converter-gson:2.3.0' 추가

sync now 클릭


3) 코드 작성

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical">
<Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="데이터 불러오기" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

 

hinfo.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="이름"
android:layout_weight="1"
android:textSize="30dp"/>
<TextView
android:id="@+id/tvPhone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="전화번호"
android:textColor="#0000ff"
android:layout_weight="1"
android:textSize="30dp"/>
</LinearLayout>
<TextView
android:id="@+id/tvAddress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="주소"
android:textColor="#00aaff"
android:textSize="20dp"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
view raw hinfo.xml hosted with ❤ by GitHub

 

hInfo.kt

package com.example.mydjngojson
// hInfo의 필드값은 Json에서 사용하고 있는 필드값과 동일한 이름이어야함.
data class hInfo (val name: String?, val phone_number: String?, val address: String?)
view raw hinfo.kt hosted with ❤ by GitHub

 

hInfoAdapter.kt

package com.example.mydjngojson
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.hinfo.view.*
// hInfo 데이터 집한을 받아서 리사이클러 뷰와 연결해주는 클래스
class hInfoAdapter(val items: List<hInfo>) : RecyclerView.Adapter<hInfoAdapter.ViewHolder> () {
// hInfoAdapter의 ViewHolder를 만들기 위한 작업
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): hInfoAdapter.ViewHolder {
// hinfo.xml 이용해서 뷰를 만들겠다!
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.hinfo, parent, false)
return ViewHolder(itemView)
}
// 해당 위치 아이템의 화면 구성하기
override fun onBindViewHolder(holder: hInfoAdapter.ViewHolder, position: Int) {
val item = items[position]
holder.setItem(item)
}
// 아이템 갯수 리턴
override fun getItemCount() = items.count()
inner class ViewHolder(itemView : View) :RecyclerView.ViewHolder(itemView) {
// hInfo애 대한 내용을 hinfo.xml과 연결
fun setItem(item: hInfo) {
itemView.tvName.text = item.name
itemView.tvPhone.text = item.phone_number
itemView.tvAddress.text = item.address
}
}
}
view raw hInfoAdapter.kt hosted with ❤ by GitHub

 

ApiService.kt

package com.example.mydjngojson
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query
// 웹에서 레트로픽방식으로 주소에 필요한 내용을 어떻게 보낼 것인지
interface ApiService {
companion object { // 정적 필드(static)
// 주소 담기
public val API_URL = "http://000.000.000.000:8000/"
}
// GET으로 tests를 통해 웹사이트 접근
@GET("tests")
// 안드로이드에서 get_tests 부를 때 파라메터 하나 들어가는데
// 그 파라메터가
// format이라는 쿼리에 들어가는 값, json이라는 문자열을 파라메터로 전달해 줘야함
fun get_tests(@Query("format") json:String) : Call<List<hInfo>>
}
view raw ApiService.kt hosted with ❤ by GitHub

 

MainActivity.kt

package com.example.mydjngojson
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_main.*
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 리사이클러뷰 매니저 설정
recyclerView.layoutManager = LinearLayoutManager(this)
// 버튼 누르면 장고에서 데이터 가져와 뷰로 출력
btn.setOnClickListener {
fetchDjango_Json()
}
}
fun fetchDjango_Json() {
// 장고에 갈 준비(레트로핏 이용)
// 레트로핏 객체 만들기(기본이 되는 url은 API_URL)
var retrofit = Retrofit.Builder().baseUrl(ApiService.API_URL).addConverterFactory(GsonConverterFactory.create()).build()
// 인터페이스 생성
var apiService = retrofit.create(ApiService::class.java)
// ?format=json
// format에 json 넣어주기
var tests = apiService.get_tests("json")
// 실행하기(비동기적으로)
tests.enqueue(object : Callback<List<hInfo>> {
// 성공 시 처리
override fun onResponse(call: Call<List<hInfo>>, response: Response<List<hInfo>>) {
// 정말 성공적으로 전달 됐는지?
if (response.isSuccessful) {
// 내용 전달 받기
var mList = response.body()!! // 절대 Null이 아님
// 리아시클러뷰에 보이게
runOnUiThread {
// recyclerView의 어댑터를 hInfoAdapter로 만들어주기
// mList를 recyclerView의 내용으로 보이게 하기
recyclerView.adapter = hInfoAdapter(mList)
}
}
}
// 실패 시 처리
override fun onFailure(call: Call<List<hInfo>>, t: Throwable) {
Log.e("D_tests", "OnFailure+${t.message}")
}
})
}
}
view raw MainActivity.kt hosted with ❤ by GitHub

실행하면 맨 위의 사진과 같은 결과가 나온다!!

우와~~~~

반응형