본문 바로가기
안드로이드 자바

[Java][Android] retrofit + 리사이클러뷰 만들기

by teamnova 2021. 11. 9.

이번시간에는 retrofit2 사용해서 리사이클러뷰를 만들어 보겠습니다.

https://stickode.com/detail.html?no=2564

스틱코드에서  [Java][Android] retrofit + 리사이클러뷰 만들기를 즐겨찾기를 해주세요.

 

스틱코드

 

stickode.com

Retrofit 이란?

REST API통신을 위해 구현된   squarup사의 OKttp 라이브러리의 상위 구현체로

통신라이브러리중 가장많이 사용되는 라이브러리 입니다.

Retrofit의 장점은 성능이 좋고, 구현이 간단하며, 가독성이 좋고, 동기/비동기의 구현이 쉽다는 것입니다.

레트로 핏은 3가지 구성요소(DTO, Interface,Retrofit.Builder클래스)로 이루어져있습니다.

 

레트로핏을 사용하는 방법은

0.Gradle 의존성을 추가합니다. 
1.메니페스트에 인터넷 권한 설정
2.모델 클래스를 생성
3.Interface를 정의
4.Retrofit 인스턴스를 생성 
5.Retrofit 인스턴스를 적용해주면 됩니다.

 

0. 먼저 Gradle의존성을 추가 합니다.

// Retrofit 라이브러리
implementation 'com.squareup.retrofit2:retrofit:2.6.4'

 

1.매니페스트의 인터넷 권한 설정을 추가합니다.

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

 

2.DTO - 모델 클래스를 생성합니다.

JSON 데이터의 속성명과 변수명 타입은 일치 해야합니다. 

package com.example.myapplication.Recipe_select;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class RetroPhoto {
    @Expose
    @SerializedName("albumId") private Integer albumId;
    @Expose
    @SerializedName("id") private Integer id;
    @Expose
    @SerializedName("title") private String title;
    @Expose
    @SerializedName("url") private String url;
    @Expose
    @SerializedName("thumbnailUrl") private String thumbnailUrl;


    public RetroPhoto(Integer albumId, Integer id, String title, String url, String thumbnailUrl) {
        this.albumId = albumId;
        this.id = id;
        this.title = title;
        this.url = url;
        this.thumbnailUrl = thumbnailUrl;
    }

    public Integer getAlbumId() {
        return albumId;
    }

    public void setAlbumId(Integer albumId) {
        this.albumId = albumId;
    }

    public Integer getId() {
        return id;
    }

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

    public String getTitle() {
        return title;
    }

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

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getThumbnailUrl() {
        return thumbnailUrl;
    }

    public void setThumbnailUrl(String thumbnailUrl) {
        this.thumbnailUrl = thumbnailUrl;
    }


}

 

 

3.Interface를 정의합니다.

package com.example.myapplication.Recipe_select;

import java.util.List;

import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.GET;

public interface GetDataService {

	// @GET/POST/PUT/DELETE 중에서 어떤작업인지 설정할수 있습니다.
    @GET("/photos")
    Call<List<RetroPhoto>> getAllPhotos();

}

 

 

4.Retrofit 인스턴스 만듭니다.

예제 사이트 :https://jsonplaceholder.typicode.com

package com.example.myapplication.Recipe_select;

import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class RetrofitClientInstance {

    private static Retrofit retrofit;
    // BaseUrl등록 
    private static final String BASE_URL = "https://jsonplaceholder.typicode.com/";

    public static Retrofit getRetrofitInstance() {
        if (retrofit == null) {
            retrofit = new retrofit2.Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    // Json을 변환해줄 Gson변환기 등록
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }
}

 

 

5. 메인액티비티에 리사이클러뷰를 넣고, 인스턴스를 적용해보겠습니다.

  Activity

package com.example.myapplication.Recipe;

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

import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.example.myapplication.Home.HomeActivity;
import com.example.myapplication.R;
import com.example.myapplication.Recipe_select.CustomAdapter;
import com.example.myapplication.Recipe_select.GetDataService;
import com.example.myapplication.Recipe_select.RetroPhoto;
import com.example.myapplication.Recipe_select.RetrofitClientInstance;
import com.example.myapplication.cookStargram.CookTalkActivity;
import com.example.myapplication.mypage.MypageActivity;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;

import org.jetbrains.annotations.NotNull;

import java.util.List;

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

public class RecipeActivity extends AppCompatActivity {

    private static final String TAG = "TestActivity-레트로핏";

	// 어답터
    private CustomAdapter adapter;
    // 리사이클러뷰
    private RecyclerView recyclerView;
    // 진행바
    ProgressDialog progressDoalog;

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

		// 진행중바 
        progressDoalog = new ProgressDialog(RecipeActivity.this);
        progressDoalog.setMessage("Loading....");
        progressDoalog.show();

        // 레트로핏 인스턴스 생성을 해줍니다.
        // enqueue로 비동기 통신을 싱행합니다.
        GetDataService service = RetrofitClientInstance.getRetrofitInstance().create(GetDataService.class);
        Call<List<RetroPhoto>> call = service.getAllPhotos();
        //통신완료후 이벤트 처리를 위한 콜백 리스너 등록
        call.enqueue(new Callback<List<RetroPhoto>>() {
        // 정상으로 통신 성공시
            @Override
            public void onResponse(Call<List<RetroPhoto>> call, Response<List<RetroPhoto>> response) {
                progressDoalog.dismiss();
                generateDataList(response.body());
            }
		// 통신 실패시(예외발생, 인터넷끊김 등의 이유)
            @Override
            public void onFailure(Call<List<RetroPhoto>> call, Throwable t) {
                progressDoalog.dismiss();
                Toast.makeText(RecipeActivity.this, "Something went wrong...Please try later!", Toast.LENGTH_SHORT).show();
            }
        });

    }
    
    
    // 리사이클러뷰 
    private void generateDataList(List<RetroPhoto> photoList) {
        recyclerView = findViewById(R.id.customRecyclerView);
        adapter = new CustomAdapter(this, photoList);
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(RecipeActivity.this);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setAdapter(adapter);
    }

}

 

 

6.Activity의 adapter

이미지 적용은 Glide를 사용했습니다.

package com.example.myapplication.Recipe_select;

import android.app.Activity;
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.recyclerview.widget.RecyclerView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.example.myapplication.R;
import com.squareup.picasso.OkHttp3Downloader;
import com.squareup.picasso.Picasso;

import java.util.List;

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomViewHolder> {

    private List<RetroPhoto> dataList;
    private Context context;

    public CustomAdapter(Context context, List<RetroPhoto> dataList) {
        this.context = context;
        this.dataList = dataList;
    }

    class CustomViewHolder extends RecyclerView.ViewHolder {

        public final View mView;

        TextView txtTitle;
        private ImageView coverImage;

        CustomViewHolder(View itemView) {
            super(itemView);
            mView = itemView;

            txtTitle = mView.findViewById(R.id.title);
            coverImage = mView.findViewById(R.id.coverImage);
        }
    }

    @Override
    public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
        View view = layoutInflater.inflate(R.layout.custom_row, parent, false);
        return new CustomViewHolder(view);
    }

    @Override
    public void onBindViewHolder(CustomViewHolder holder, int position) {

		// 타이틀
        holder.txtTitle.setText(dataList.get(position).getTitle());
		// 이미지 
        Glide.with(context)
                .load(R.drawable.ic_rabbit)
                .skipMemoryCache(true)
                .circleCrop()
                .skipMemoryCache(true)
                .error(R.drawable.ic_rabbit)
                .diskCacheStrategy(DiskCacheStrategy.NONE)
                .into(holder.coverImage);
    }

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

 

 

7.Activity.xml 안에 리사이클러뷰 큰 틀을 넣어줍니다.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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=".Recipe.RecipeActivity">

	// 리사이클러뷰
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/customRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="620dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</RelativeLayout>

 

 

8.customrow.xml / 아이템 xml을 만들어줍니다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view_friend"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    card_view:cardUseCompatPadding="true"
    >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >

        <ImageView
            android:id="@+id/coverImage"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_alignParentStart="true"
            android:layout_alignParentTop="true"
            android:scaleType="centerCrop"
            android:layout_alignParentLeft="true" />

        <TextView
            android:id="@+id/title"
            style="@style/TextAppearance.AppCompat.Medium"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@+id/coverImage"
            android:layout_marginLeft="16dp"
            android:paddingTop="20dp"
            android:lines="2"
            android:text="title" />

    </RelativeLayout>

</androidx.cardview.widget.CardView>

 

 

 

9.적용된 모습입니다.

스티코드를 잘 활용해서 만들어 보세요!  

https://stickode.com/detail.html?no=2564

 

스틱코드

 

stickode.com