안드로이드 스튜디오 기초(4) — 뉴스 앱 만들기 2

Nanyoung Kim
11 min readMay 1, 2020

--

참고 : 유투브 — 센치한 개발자

<News api 로 서버에서 실제 뉴스 불러오기>

[1. API KEY 받기]

[2. 받아올 데이터 확인]

[3. 카드 뷰 디자인 확인]

[4. 종속성 추가]

  • line 37,38을 추가한 후 Sync Now 를 클릭하여 싱크를 맞춰준다.

목표 : 네트워크 뉴스 정보를 받아와서 이를 json 값으로 변환하여 세팅하고 Fresco를 통해서 이미지도 가져올 것이다.

[5. 기사를 가져오는 getNews() 생성]

  • line 59 : getNews() 를 생성하고 내용을 넣는다. 그 내용은 이 링크를 참고한다. (https://developer.android.com/training/volley/simple )
  • line 29,48 : queue 전역 변수로 바꾸고 초기화를 해준다.
  • line 61 : String url 에 google 의 주소 대신 south korea news api 의 주소를 넣는다.
  • line 64 : 데이터를 GET 방식으로 가져온다.
  • line 72,73 : 정상적으로 정보를 받아온 경우에 어댑터로 정보를 넘기도록 코드를 이곳에 옮긴다.
  • JSON String 형태 그 자체는 값을 다루기 어려우므로 JSON 오브젝트 형태로 바꾸어 다루기 쉽게 한 후 어댑터에 값을 넘겨줄 것이다.
  • 그러나 onResponse() 의 파라미터가 String 형이다.(line 67) 이것을 어떻게 바꿀 것인가? => 값을 표시할 어댑터가 쓰레기값을 남기지 않도록 필요한 값만 분류하는 작업을 해줘야한다. => 이 작업을 해주는 클래스가 필요하다.(NewsData.java)

[6. 받아온 데이터를 필요한 부분만 분류하기]

  • NewsData.java 라는 자바 클래스를 새로 생성한다.
  • 우리는 위 화면에서 title, urlToImage, description 이 세가지 데이터만 필요하다.
  • Serializable(직렬화) : 데이터가 많고 숫자나 문자가 아닌 데이터 타입일 때 이것을 하나의 데이터 구조로 바꾸어 넘겨주고 받기 위함이다. intent 할 때 간혹 쓰인다.
  • private 형으로 변수 세개(title, urlToimage,description) 를 선언한 후 오른쪽 버튼 클릭>Getter and Setter>셋 다 선택 후 OK 를 하면 아래와 같은 함수들이 생성된다.
결과(content는 description으로 바꿔야 함)
  • line 75 : 기사 여러개를 받아와야 하므로 List 형을 선언한다.
  • line 76 : 기사 한 개에 해당하는 데이터를 받아 올 newsData 를 선언한다.
  • line 79 : List에 받아온 기사 데이터를 add 한다.
  • line 82,83 : 데이터를 다 받고 그 List를 어댑터에 넘긴다.

[7. 기사 데이터 받아오기]

이제 기사에 대한 정보를 받아와보자.

그 전에 데이터의 구조를 살펴보자.

  • 처음에 json 을 읽어서 ( ‘[‘ 가 시작되는 부분이 제이슨 시작) ‘articles’라는 key 값의 ‘배열 value’ (‘[‘ 시작 부분)를 가져와서 그 value 안에 있는 json을 하나씩 가져오면 된다. 그 가져온 json 한 개 안에 있는 title, urlToImage,description 를 빼 오는 것이 우리의 목표이다.
  • 받아온 response 를 json 형태로 바꿔준다.
  • json 형식을 지닌 string (json string) 이라는 가정 하에 JSONObject 로 바꾼다. 그럼 오류가 발생하는데 try-catch 구문으로 해결한다. (Json 형태가 아닌데 바꾸려고 하는 경우가 있을 수도 있기 때문에 예외 처리.)
  • “articles” 라는 키 값을 가진 value (여기서는 배열 형태의 value) 를 가져온다.
  • 배열에서 하나씩 값을 가져오기 위해 for 문을 이용한다.
  • obj.getString() 에서 String 은 value 값이 string 이라는 뜻이다.(author, title, url … 등에 해당 안됨)

[8. 로그 찍어보기]

  • line 88 : 제대로 값을 가져왔는지 알기 위해 Log 를 찍어보자.
  • 로그가 뜨지 않는 오류가 발생했다. 원인은 아직 찾지 못하였다.

[10. 어댑터로 넘겨 받은 데이터 다루기]

  • 분류한 NewsData 변수의 정보를 토대로 onBindViewHolder에서 값을 다룬다.
  • onBindViewHolder 가 원본 데이터의 크기만큼 반복한다는 것을 힌트 삼아서 뉴스를 꺼내야 한다.
  • positon : 이 위치에 해당하는 정보를 가져올 수 있게 한다. => 리사이클러뷰의 항목 __ 번째 = 데이터의 __ 번째
  • 이미지 파일의 위치는 url 로 알고 있으니 fresco 를 통해 이미지를 불러와야 한다.

<Fresco 사용법>

참고 — https://frescolib.org/docs/index.html

step 1) 초기화하기

  • 위의 line 6을 아래의 line 46에 복사 & 붙여넣기 한다. (초기화 과정)

step 2) 전용뷰 xml

  • 위를 참고하여 아래와 같이 row_news.xml 파일을 수정한다.

step 3) 이미지 로딩

  • 위를 참고하여 아래와 같이 MyAdapter.java 를 수정한다.
  • line 30 : Fresco는 이미지를 표시하기 위해 전용 레이아웃 컴포넌트인 SimpleDraweeView를 사용한다.
  • line 83 : 삼항 연산자를 이용하여 받아온 값이 null 일때도 조건문 통해 처리해준다.

<Fresco 초기화 시 오류 해결>

  • 오류가 나는 이유 : context는 기본적으로, 안드로이드 내에서 Activity 에서 쓰이는 것이다. 그래서 Adapter 같은 평범한 클래스에서는 쓸 수 없다. => context 를 받아와야 한다.

오류를 해결해보자.

NewsActivity 에서 파라미터(this)를 하나 더 넘겨준다.

MyAdapter에서 파라미터를 받아서 쓴다.

그러나 맹점이 있다. 액티비티에서 넘겨 받은 값을 어댑터에서 계속 쓰고 있으면 메모리 누수 현상이 발생한다. (별로 권장하지 않는 방법이나 쉬운 방법임)

[참고 — permission]

line 5 : 안드로이드 폰의 인터넷에서 정보를 받으려면 permission 이 필요하다. => 좌측 상단의 app>manifests>AndroidManifest.xml 에서 permission 를 추가해준다.

[결과 확인]

  • 빌드를 해보면 아까는 찍히지 않았던 로그가 잘찍히고
  • 실행 화면도 잘 나오는 것을 확인할 수 있다.

description 이 null 일 때 예외 처리

[11. 기사 클릭 시 본문으로 가기]

  • 어댑터를 넘길 때 클릭 리스너도 같이 넘긴다.
  • MyViewHolder의 파라미터 View : 이 홀더가 가지는 레이아웃 ‘row_news.xml’ 제일 바깥에 있는 루트이다.
  • line 38 : onBindViewHolder에서 클릭 리스너를 다는 경우도 있으나, 이 경우에는 for문을 계속 돌면서 set을 하기 때문에 비추한다. => MyViewHolder 에 리스너를 달자.
  • line 38 : 오류가 나는 이유는 위에서 선언해준 onClickListner이 static 변수가 아니기 때문이다.
  • line 22 : static 형으로 수정해주면 오류가 해결된다.
  • 그러나 파라미터 View 의 가장 바깥 요소는 row_news.xml 파일의 Linear Layout 이기 때문에 line 39, 40 과 같이 셋팅을 해준다. 이제 기사의 이미지,타이틀,내용 중 어디든 눌러도 기사 본문으로 넘어갈 수 있게 준비해 놓은 상태이다.

이제 액티비에서 리스너를 어댑터에 넘겨줘보자.

  • line 100~105 : 넘길 수 있게 셋팅.
  • 이제 line 103에서 리스트에 담았던 데이터들을 다룰 수 있도록 코드를 짜야한다. => 클릭한 뷰가 몇번째 뷰인지 순번을 매겨줘야 리스트에서 몇번째 데이터(기사) 인지 구분할 수 있다. (이 문제로 position을 사용하기 위해 onBindViewHolder에 클릭 리스너를 달기도 하는데 그냥 ‘View v’에 tag(label)만 달아주면 된다.
  • 그렇다면 onBindViewHolder에 v 를 어떻게 가져올까? => ‘holder.~’로 가져오면 된다. => 선언한 후 초기화 시켜줘야 한다. (line32,39)
  • line 95 : 이제 holder 를 이용해 View들에 태그를 달 수 있다.
  • 이렇게 단 태그는 액티비티에서 쓰기 위함이다.
  • line 105 : v.getTag() 를 하면 오브젝트가 나오기 때문에 int position 에 대입하려면 형 변환을 해줘야 한다.
  • 이렇게 가져온 position 값으로 뉴스 기사 정보가 담긴 리스트에 접근을 해야 한다.=> 어댑터로 넘겼으니 그 넘긴 값(mDataSet)을 가져와야 하고 가져오기 위해서는 함수를 하나 만들어야 한다.
  • line 108~110 : 위와 같은 함수를 하나 생성해준다.
  • 그 후 액티비티에서 getNews() 를 쓰기 위해 mAdapter.getNews() 를 해 보려고 하면 안 된다.
  • 그 이유 : mAdapter 의 데이터 타입은 RecyclerView.Adapter이기 때문이다. (line 33)
  • 그래서 우리는 클래스 형 변환을 해 줘야 한다. (클래스의 자식과 부모가 누구인지 아는것)

Sign up to discover human stories that deepen your understanding of the world.

--

--

Responses (1)

Write a response