개발/Android

[안드로이드/Java] RecyclerView와 DB연동

Eun 2021. 5. 12. 01:13

RecyclerView를 사용하여 DB연동을 하여 데이터를 출력해보도록 하겠다.

 

우선 결과는 아래와 같다.

그렇다면 구현해보자!

 

1. RecyclerView 만들기

activity_vote_list.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_vote_list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
        </androidx.recyclerview.widget.RecyclerView>

        <Button
            android:id="@+id/btn_create_vote"
            android:text="투표 생성"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_below="@id/rv_vote_list">
        </Button>

</RelativeLayout>

리사이클러뷰를 활용한 화면을 구성한다.

나는 간단하게 RecyclerView와 Button만 넣어주었다.

 

2. RecyclerView의 ItemView 만들기

listview_vote.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

        <TextView
            android:id="@+id/tv_vote_college"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_centerInParent="true"
            android:gravity="center"
            android:text="테스트입니다.">
        </TextView>

</RelativeLayout>

recyclerView에 적용할 아이템 하나에 대한 레이아웃을 만들어준다.

간단하게 TextView하나만 넣어주었다.

 

preview

3. Adapter 만들기

ListViewVoteAdapter.java

package com.example.myapplication.Activity.Adapter;

import android.content.Context;
import android.content.Intent;
import android.os.Parcelable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.example.myapplication.Activity.CandidateListActivity;
import com.example.myapplication.Activity.ListViewVote;
import com.example.myapplication.R;

import java.util.ArrayList;

public class ListViewVoteAdapter extends RecyclerView.Adapter {

    private Context tv_vote_name;

    //Adapter에 들어갈 list
    private ArrayList<ListViewVote> listViewVoteList = new ArrayList<ListViewVote>();

    //ListViewAdapter의 생성자
    public ListViewVoteAdapter (Context tv_vote_name, ArrayList<ListViewVote> listViewVoteList) {
        this.tv_vote_name = tv_vote_name;
        this.listViewVoteList = listViewVoteList;
    }


    //LayoutInflater를 이용하여 전 단계에서 만들었던 listview_vote.xml을 inflate 시킨다.
    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater infalter = LayoutInflater.from(tv_vote_name);
        View itemView = infalter.inflate(R.layout.listview_vote,parent,false);

        VH holder = new VH(itemView);
        return holder;
    }

    //item을 하나하나 bind 되는 함수
    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        VH vh = (VH)holder;

        ListViewVote item = listViewVoteList.get(position);
        vh.vote_college.setText(item.getCollege());

    }

    //지정한 위치(position)에 있는 데이터와 관계된 아이템(row)의 ID를 리턴
    @Override
    public long getItemId(int position) {
        return position;
    }

    //RecyclerView의 총 개수
    @Override
    public int getItemCount() {
        return (listViewVoteList == null) ? 0 : listViewVoteList.size();
    }

    class VH extends RecyclerView.ViewHolder {
        
        TextView vote_college;

        public VH(@NonNull View itemView) {
            super(itemView);

            vote_college=itemView.findViewById(R.id.tv_vote_college);
            vote_college.setClickable(true);
            vote_college.setOnClickListener(new View.OnClickListener() {

                //recycler의 item이 클릭되면 실행
                @Override
                public void onClick(View v) {
                    int position = getAdapterPosition();
                    if(position!=RecyclerView.NO_POSITION){
                        Intent intent = new Intent(tv_vote_name, CandidateListActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                        intent.putExtra("college", listViewVoteList.get(position).getCollege());

                        tv_vote_name.startActivity(intent);
                    }
                }
            });

        }
    }
}

RecyclerView의 경우 아이템을 표시하기 위해 생성한 뷰를 재활용한다.

재활용하기위해 뷰홀더(ViewHolder)패턴을 사용한다.

뷰홀더는 화면에 표시될 아이템 뷰를 저장하는 객체이다. 미리 생성된 뷰홀더 객체가 있는 경우에는 새로 생성하지 않고 재활용하는데,

이때 단순히 데이터가 뷰홀더의 아이템 뷰에 바인딩된다.

 

그리고 사용자의 데이터 목록을 아이템 뷰로 만들기 위해 어댑터(Adapter)를 사용한다.

아래의 그림을 보면 이해가 더 쉬울 것이다. 

 

어댑터를 통해 만들어진 각 아이템 뷰는 뷰홀더객체에 저장되어 화면에 표시되고, 필요에 따라 생성 또는 재활용되는 것이 리사이클러뷰의 특징이다!

 

4. Data Class 만들기

ListViewVote.java

package com.example.myapplication.Activity;


//  소속대학이름을 클래스에 담기 위한 선언
public class ListViewVote {
    private String college;

    public void setCollege(String college) {
        college = college;
    }

    public String getCollege() {
        return this.college;
    }

    public ListViewVote(String college) {
        this.college = college;
    }
}

listview_vote.xml에 작성한 TextView에 들어갈 데이터를 저장할 class이다.

 

5. MainAcitivity 작성

VoteListActivity.java

package com.example.myapplication.Activity;

import android.content.Intent;
import android.os.Bundle;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.toolbox.Volley;
import com.example.myapplication.Activity.Adapter.ListViewVoteAdapter;
import com.example.myapplication.R;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;

public class VoteListActivity extends AppCompatActivity {

    RecyclerView recyclerView;
    private ArrayList<ListViewVote> listViewVoteList = new ArrayList<ListViewVote>();
    private ListViewVoteAdapter adapter;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_vote_list);


        //로그인 한 학번 받아오기
        Intent UserNumberIntent = getIntent();
        String UserNumber = UserNumberIntent.getExtras().getString("UserNumber");

        //adapter와 recyclerView 연결
        recyclerView = findViewById(R.id.rv_vote_list);
        adapter = new ListViewVoteAdapter(this, listViewVoteList);
        recyclerView.setAdapter(adapter);


        //LinearLayoutManager와 recyclerView 연결
        LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(layoutManager);

        Response.Listener<String> responseListener = new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                adapter.notifyDataSetChanged();

                try {
                    JSONArray jsonArray = new JSONArray(response);

                    //아이템의 개수만큼 파싱하기
                    for (int i = 0; i < response.length(); i++) {
                        JSONObject jObject = jsonArray.getJSONObject(i);
                        String college = jObject.getString("college");

                        //아이템의 개수만큼 recyclerView에 객체 넣어주기
                        listViewVoteList.add(new ListViewVote(college));
                        adapter.notifyItemInserted(0);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        };

        //받아온 학번(UserNumber)를 서버에 보내기
        VoteListRequest votelistRequest = new VoteListRequest(UserNumber,responseListener);
        RequestQueue requestQueue = Volley.newRequestQueue(this);
        requestQueue.add(votelistRequest);

    }

}


 

코드가 조금 길지만 recyclerView를 구현하는데 핵심은 아래와 같다.

RecyclerView객체와 Adapter 객체 연결,  RecyclerView 객체와 LinearLayoutManager객체 연결!

그리고 이 어댑터에 data에 추가해주어야하는데 그것은 add()를 통해서한다.

서버로부터 받은 응답(array)를 파싱을 해주어 add를 해준 것을 볼 수 있다. 

6. Request.java 작성

VoteListRequest.java

package com.example.myapplication.Activity;
import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.toolbox.StringRequest;

import java.util.HashMap;
import java.util.Map;

public class VoteListRequest extends StringRequest {

    final static  private String URL="http://voting.dothome.co.kr/Voting_List.php";
    private Map<String, String> map;

    public VoteListRequest(String student_number,Response.Listener<String> listener) {
        super(Request.Method.POST, URL, listener, null);

        map = new HashMap<String, String>();
        map.put("UserNumber", student_number);

    }

    @Override
    protected Map<String, String> getParams() throws AuthFailureError {
        return map;
    }
}

 

url에 주소를 저장하고 받아온 UserNumber를 서버로 보내기위해 map에 담아 요청하였다.

 

7. php 작성

Voting__List.php

<?php
    $con = mysqli_connect("localhost", "ftp아이디", "ftp비밀번호", "ftp아이디");
    // mysqli_query($con,'SET NAMES utf8');
 
    $student_number = $_POST["UserNumber"];
    
    $statement = mysqli_query($con, "SELECT college FROM VotingTb WHERE student_number = '$student_number'");

    $rowCnt= mysqli_num_rows($statement);
 
    $arr= array(); //빈 배열 생성
 
    for($i=0;$i<$rowCnt;$i++){
        $row= mysqli_fetch_array($statement, MYSQLI_ASSOC);
        //각 각의 row를 $arr에 추가
        $arr[$i]= $row;
    }

    //배열을 json으로 변환하는 함수가 있음.
    $jsonData=json_encode($arr); //json배열로 만들어짐.
    echo "$jsonData";

    mysqli_close($conn);
 
?>

DB와 연동해주고 array로 응답을 보낸다.

 

 

여기까지 코드작성은 끝났다. 

 ^0^ DB로 부터 받아온 결과를 리사이클러뷰에 출력하였다. 성공!^^!

 


참고

- 안드로이드 리사이클러뷰 기본 사용법

 

안드로이드 리사이클러뷰 기본 사용법. (Android RecyclerView)

1. 안드로이드 리사이클러뷰(RecyclerView) 리사이클러뷰(RecyclerView)는, "많은 수의 데이터 집합을, 제한된 영역 내에서 유연하게(flexible) 표시할 수 있도록 만들어주는 위젯"입니다. [안드로이드 개발

recipes4dev.tistory.com

- 안드로이드 리사이클러뷰 기본 사용법

 

[RecyclerView] 안드로이드 리사이클러뷰 기본 사용법

안드로이드 RecycleView 기본 사용법  안드로이드 앱을 개발 하다보면 옛날에는 ListView(리스트뷰)를 많이 썼지만 요즘엔 리스트뷰의 거의 모든 기능을 RecyclerView(리사이클러뷰)로 할 수 있기때문

dev-imaec.tistory.com

- 안드로이드 스튜디오 JSON으로 DB데이터 불러오기

 

Android Studio(기능) JSON 으로 DB데이터 불러오기

위와 같이 DB에 데이터와 이미지가 저장되어 있다. 이것을 JSON으로 불러오는 예제이다. 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

lcw126.tistory.com