군침이 싹 도는 코딩

retrofit2 라이브러리를 이용한 RecyclerView 화면 처리법 본문

Android

retrofit2 라이브러리를 이용한 RecyclerView 화면 처리법

mugoori 2023. 2. 9. 16:12
{
    "result": "success",
    "items": [
        {
            "id": 18,
            "title": "점심",
            "datetime": "2023-03-11T17:30:00",
            "content": "맛있는 점심3",
            "createdAt": "2023-01-06T04:02:42",
            "updatedAt": "2023-01-06T04:02:42"
        },

# 해당 예시처럼 결과를 가져와서 리사이클러뷰에 표시하는법을 알아보자

 

 

 

package com.mugoori.memoapp.model;

import java.io.Serializable;
import java.util.List;

public class MemoList implements Serializable {

    private String result;
    private List<Memo> items;
    private int Count;

    public MemoList(){

    }

    public MemoList(String result, List<Memo> items, int count) {
        this.result = result;
        this.items = items;
        Count = count;
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    public List<Memo> getItems() {
        return items;
    }

    public void setItems(List<Memo> items) {
        this.items = items;
    }

    public int getCount() {
        return Count;
    }

    public void setCount(int count) {
        Count = count;
    }
}

# 해당 결과를 받을수있게 모델 패키지에 MemoList라는 클래스로 만들어 결과를 받아주도록한다

 

 

 

package com.mugoori.memoapp.model;

import java.io.Serializable;

public class Memo implements Serializable {

    private int id;
    private String title;
    private String datetime;
    private String content;
    private String createdAt;
    private String updatedAt;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDatetime() {
        return datetime;
    }

    public void setDatetime(String datetime) {
        this.datetime = datetime;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(String createdAt) {
        this.createdAt = createdAt;
    }

    public String getUpdatedAt() {
        return updatedAt;
    }

    public void setUpdatedAt(String updatedAt) {
        this.updatedAt = updatedAt;
    }
}

# 리사이클러뷰에 표시할 데이터는 Api 명세서를 봤을때 items 라는 어레이리스트안에 들어가있다

따라서 이것을 따로 받아줄 클래스를 모델 패키지에 만들어준다

 

 

 

<?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"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginLeft="15dp"
        android:layout_marginTop="7dp"
        android:layout_marginRight="15dp"
        android:layout_marginBottom="7dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="10dp"
            android:orientation="horizontal">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="4"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/txtTitle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="제목"
                    android:textSize="24sp" />

                <TextView
                    android:id="@+id/txtDate"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="15dp"
                    android:text="날짜"
                    android:textSize="24sp" />

                <TextView
                    android:id="@+id/txtContent"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="15dp"
                    android:text="내용"
                    android:textSize="24sp" />
            </LinearLayout>

            <ImageView
                android:id="@+id/imgDelete"
                android:layout_width="40dp"
                android:layout_height="40dp"
                app:srcCompat="@drawable/baseline_close_24" />
        </LinearLayout>

    </androidx.cardview.widget.CardView>
</LinearLayout>

# 리사이클러뷰에 표시할 행을 만들어준다

 

 

 

package com.mugoori.memoapp.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

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

import com.mugoori.memoapp.R;
import com.mugoori.memoapp.model.Memo;

import java.util.ArrayList;

public class MemoAdapter extends RecyclerView.Adapter<MemoAdapter.ViewHolder> {

    Context context;
    ArrayList<Memo> memoList;

    public MemoAdapter(Context context, ArrayList<Memo> memoList) {
        this.context = context;
        this.memoList = memoList;
    }

    @NonNull
    @Override
    public MemoAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.memo_row, parent, false);
        return new MemoAdapter.ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MemoAdapter.ViewHolder holder, int position) {
        Memo memo = memoList.get(position);

        holder.txtTitle.setText(memo.getTitle());
        // "2023-08-03T11:30:00"
        // "2023-08-03 11:30:00"
        // "2023-08-03 11:30"
        String date = memo.getDatetime().replace("T", " ")
                .substring(0, 15+1);
        holder.txtDate.setText(date);
        holder.txtContent.setText(memo.getContent());

    }

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

    public class ViewHolder extends RecyclerView.ViewHolder{

        TextView txtTitle;
        TextView txtDate;
        TextView txtContent;
        ImageView imgDelete;

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

            txtTitle = itemView.findViewById(R.id.txtTitle);
            txtDate = itemView.findViewById(R.id.txtDate);
            txtContent = itemView.findViewById(R.id.txtContent);
            imgDelete = itemView.findViewById(R.id.imgDelete);

        }
    }
}

# 행과 데이터를 연결할 어댑터도 만들어준다

 

 

package com.mugoori.memoapp.api;

import com.mugoori.memoapp.model.MemoList;

import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Query;

public interface MemoApi {

    // 내 메모 가져오는 APi
    @GET("/memo")
    Call<MemoList> getMemoList(@Header("Authorization") String token, @Query("offset") int offset, @Query("limit") int limit);
}

# Api 설계를 위해 api 패키지에 MemoApi로 만들어준다

이때 GET 방식이므로 바디에는 데이터가 없고 헤더의 JWT 토큰과 쿼리 스트링으로 오프셋

리미트를 보내주도록한다

 

 

package com.mugoori.memoapp;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.mugoori.memoapp.adapter.MemoAdapter;
import com.mugoori.memoapp.api.MemoApi;
import com.mugoori.memoapp.api.NetworkClient;
import com.mugoori.memoapp.config.Config;
import com.mugoori.memoapp.model.Memo;
import com.mugoori.memoapp.model.MemoList;

import java.util.ArrayList;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;

public class MainActivity extends AppCompatActivity {

    Button btnAdd;
    ProgressBar progressBar;

    RecyclerView recyclerView;
    MemoAdapter adapter;
    ArrayList<Memo> memoArrayList = new ArrayList<>();

    String accessToken;

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


        // 억세스토큰이 저장되어있으면 로그인한 유저이므로 메인액티비티를 실행하고
        // 그렇지않으면 회원가입 액티비티를 실행하고 메인액티비티는 종료

        SharedPreferences sp = getSharedPreferences(Config.PREFERENCE_NAME,MODE_PRIVATE);
        accessToken = sp.getString(Config.ACCESS_TOKEN,"");

        if (accessToken.isEmpty()){
            Intent intent = new Intent(MainActivity.this,RegisterActivity.class);
            startActivity(intent);
            finish();
            return;

        }

        // 회원가입 / 로그인 유저이면 아래 코드를 실행하도록한다
        btnAdd = findViewById(R.id.btnAdd);
        progressBar = findViewById(R.id.progressBar);

        recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));

        // 네트워크로부터 내 메모를 가져온다
        getNetworkData();

    }

    private void getNetworkData() {
        progressBar.setVisibility(View.VISIBLE);

        Retrofit retrofit = NetworkClient.getRetrofitClient(MainActivity.this);
        MemoApi api = retrofit.create(MemoApi.class);

        Call<MemoList> call = api.getMemoList("Bearer "+accessToken,0,20);

        call.enqueue(new Callback<MemoList>() {
            @Override
            public void onResponse(Call<MemoList> call, Response<MemoList> response) {
                progressBar.setVisibility(View.GONE);

                if ( response.isSuccessful() ){

                    // 정상적으로 데이터 받았으니 리사이클러뷰에 표시
                    MemoList memoList = response.body();

                    memoArrayList.addAll(memoList.getItems());

                    adapter = new MemoAdapter(MainActivity.this,memoArrayList);
                    recyclerView.setAdapter(adapter);


                }else {
                    Toast.makeText(MainActivity.this, "서버에 문제가 있습니다", Toast.LENGTH_SHORT).show();
                    return;
                }
            }

            @Override
            public void onFailure(Call<MemoList> call, Throwable t) {
                progressBar.setVisibility(View.GONE);

            }
        });
    }
}

# 이제 메인액티비티로 돌아가서 화면을 연결하고 레트로핏을 통해 네트워크로부터 내 메모를 받아와서

어댑터를 통해 리사이클러뷰와 연결한다