[AndroidStudio] Retrofit을 활용해서 RecyclerView로 게시판 만들기

Hyebin Lee·2022년 1월 23일
0

AndroidStudio

목록 보기
2/3
post-custom-banner

참고한 링크

  1. Retrofit2로 데이터 받아 와서 RecyclerView 만들기

오늘은 RecyclerView를 활용해서 게시판을 만들어 볼 예정이다!
DB에 있는 게시글 데이터를 Retrofit으로 불러와서 게시판에 찍어내는 과정까지 해보려고 한다.
오늘도 파이팅❣❣

1. Retrofit 관련 설정하기

이 부분은 Retrofit 완전 정복을 향해🤸‍♀️ 게시글에서 자세히 다루고 있기 때문에 상세한 코드는 생략하도록 하겠다.

  • 먼저 build.gradle과 retrofitclient 클래스를 생성한다
  • 불러온 게시판 데이터 양식과 일치하는 data 클래스를 생성한다
  • api interface를 생성한다.
  • RecyclerView로 layout을 설정할(게시판 리스트를 보여줄) Activity 파일에서 apiInterface 객체를 선언하고 enqueue함수에서 onResponse까지 override 과정을 마친다.

2. RecyclerView 레이아웃 만들기

RecyclerView에는 layout이 두 개가 필요하다.
하나는 Recycler하게 목록을 띄울 화면 레이아웃이고 또 하나는 목록 하나하나, 즉 각 View행 마다의 공통된 레이아웃이다.

RecyclerView는 각 View행 하나를 재활용해서 여러 개 띄워낸다는 의미를 갖고 있다. 그 의미에 걸맞게 띄우고 싶은 형식이 반복(중복)되는 레이아웃을 하나 생성하고 그 레이아웃을 띄울 하나의 화면을 만들면 되는 것이다.

  • Recycler하게 목록을 띄울 화면 레이아웃
<?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/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
 
</androidx.constraintlayout.widget.ConstraintLayout>

예시니까 간단하게 recyclerView 만 넣었지만 해당 화면에 다른 요소들을 넣고 싶다면 기존의 화면 레이아웃 구성처럼 다양하게 해도 무방하다. 단지 recyclerView 영역에서 view 아이템들이 recycle된다는 것만 알고 있으면 된다.

  • 개별 View 아이템 행 레이아웃
<?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"
    android:orientation="vertical"
    android:weightSum="100"
    android:padding="5dp">

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="100dp"
        android:layout_gravity="center"
        android:background="#F2F8EB"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="2.5"
            android:background="#A5E4DF"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/tv_postlist_title"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:gravity="center|left"
                android:text="Title" />

            <TextView
                android:id="@+id/tv_postlist_timestamp"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="center|right"
                android:layout_weight="2"
                android:background="@color/teal_200"
                android:gravity="center|right"
                android:text="2022-01-01-XX:XX:XX"
                android:textSize="10sp" />
        </LinearLayout>

        <TextView
            android:id="@+id/tv_postlist_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center|left"
            android:text="Content" />
    </LinearLayout>

</LinearLayout>


디자인 옵션에서 보는 예시의 레이아웃은 이런 느낌이다.

이 레이아웃은 그냥 하나의 예시일 뿐 개발자의 입맛에 맞게 충분히 유연하게 바꿔주어도 된다.
그냥 한 가지 알아야 할 점은 이 파일은 activity가 아니라 layout이라는 점! 그리고 여기서 만들어준 layout이 위의 recyclerview위치에서 반복될거라는 점이다.

3. RecyclerView Adapter 만들기

RecyclerView는 ListView와는 다르게 한 화면에서 표기하기 힘든 많은 양의 데이터를 스크롤 기능을 지원해서 계속해서 스크롤하면 재생산해낼 수 있도록 하는 위젯이다. 여기서 재활용이라는 의미의 recycle 이름을 따게 된 것이다. 위의 view 아이템 layout 틀을 재활용하기 위해서는 Adapter로 itemView를 만들어내야 한다.
구현할 Adapter에는 크게 Adapter와 Holder 두 가지가 있는데

  • Holder는 위의 각 View 아이템 틀에 해당하는 itemView를 틀 형태로 만들어준다.
  • Adpater는 Holder가 만들어준 itemView 틀을 inflater를 이용해 객체화하고 안에 실제 데이터를 담아준다.
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.Toast;

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

import org.techtown.knockknock.R;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

//Adapter : listview를 만들어서 recyclerview와 연결해줌 , Holder에서 만들어 준 listView를 inflater를 이용해 객체화 시키고 실제 데이터를 담아줌
//즉, Holder가 listview 그릇을 만들면 Adapter가 실제 데이터를 담은 listView를 만들어주는 것.
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {

private Context c;
private List<PostData> postlist;

public RecyclerAdapter(Context c, List<PostData> postlist){
    this.c = c;
    this.postlist = postlist;
}

@NonNull
@Override
public RecyclerAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){

    //inflater: xml을 객체화
    View view = LayoutInflater.from(c).inflate(R.layout.listview_post,parent,false);
    return new MyViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull RecyclerAdapter.MyViewHolder holder, int position){
    holder.title.setText(postlist.get(position).getTitle());
    holder.date.setText(postlist.get(position).getDate());
    holder.content.setText(postlist.get(position).getContent());
}

    @Override
    public int getItemCount() {
    int size = postlist.size();
        return size;
    }

    //Holder: 레이아웃과 연결해서 listView를 만들어주는 역할 (단순 연결)
    public class MyViewHolder extends RecyclerView.ViewHolder {

        TextView title;
        TextView content;
        TextView date;

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

            title = (TextView)itemView.findViewById(R.id.tv_postlist_title);
            content = (TextView)itemView.findViewById(R.id.tv_postlist_content);
            date = (TextView)itemView.findViewById(R.id.tv_postlist_timestamp);

        }
    }

}

MyViewHolder 안의 멤버변수는 당연히 View 아이템 레이아웃의 구성요소와 일치해야 한다.

4. RecyclerView 사용하기

이제 다시 RecyclerView layout이 올라가있는 Activity파일에서 사용을 위한 추가 사항만 추가해주면 된다.

public class UserPostActivity extends AppCompatActivity {

    TextView writerInfo;

    // 우선 데이터를 담을 list를 하나 만든다.
    PostListData postlist; //📌
    List<PostData> postInfo; //📌

    RecyclerView recyclerView; //📌
    RecyclerAdapter recyclerAdapter; //📌

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_user_post);

	//📌
        postInfo = new ArrayList<>();
        recyclerView = findViewById(R.id.recyclerView);
	//📌
        //layoutManager: recyclerview에 listview 객체를 하나씩 띄움
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);

        //sharedPreferences 에서 현재 로그인 되어있는 유저의 id가져오기
        SharedPreferences sharedPreferences = getSharedPreferences("UserInfo",MODE_PRIVATE);
        String id = sharedPreferences.getString("userId","");
        String nickname = sharedPreferences.getString("nickname","");

        writerInfo = findViewById(R.id.tv_writerInfo);
        writerInfo.setText(nickname+" 님이 작성하신 글 입니다.");

        PostAPI postAPI = RetrofitClient.getInstance().create(PostAPI.class);
        Call<PostListData> call = postAPI.getPostListDatabyUserId(id);
        call.enqueue(new Callback<PostListData>() {
            @Override
            public void onResponse(Call<PostListData> call, Response<PostListData> response) {
                if(response.isSuccessful()){
                postlist = response.body();
                Log.d("UserPostActivity",postlist.toString());
                postInfo = postlist.data;
		//📌	
                //Adapter를 이용해서 postInfo에 있는 내용을 가져와서 저장해둔 listView 형식에 맞게 띄움
                recyclerAdapter = new RecyclerAdapter(getApplicationContext(),postInfo);
                recyclerView.setAdapter(recyclerAdapter);
                }

                else{
                    ErrorBody errorBody = new Gson().fromJson(response.errorBody().charStream(),ErrorBody.class);
                    Log.d("UserPostActivity",errorBody.getMessage());
                }
            }

            @Override
            public void onFailure(Call<PostListData> call, Throwable t) {
                    Log.d("UserPostActivity",t.toString());
            }
        });



    }
}

📌 표시된 부분과 유사하게 코드에 맞춰 추가해주면 Recycler View 활용까지 완료할 수 있다!

5. RecyclerView의 각 ViewItem Click Event 생성하기

이 부분은 개발일지에서 자세히 다루고 있어서 다음 링크를 참고하면 될 것이다 🥰

⭐ RecyclerView 구현 시 주의사항

Item view의 가장 상위 layout의 height는 반드시 match_parent가 아니여야 한다! match_parent로 줘버리면 recyclerview 부분을 하나의 item view가 다 덮어버려서 아이템이 하나밖에 안뜬다. 이거 때문에 버그인줄 알고 이틀 헤맴 ㅠㅠㅠㅠㅠ

post-custom-banner

0개의 댓글