activity_main.xml ์์ฑํ๊ธฐ
<?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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<Button
android:id="@+id/btnAdd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerInParent="false"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:text="์ง์ ์ถ๊ฐ"
android:textSize="30sp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/btnAdd" />
<ProgressBar
android:id="@+id/progressBar2"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/btnAdd"
android:layout_centerHorizontal="true"
android:layout_marginTop="316dp"
android:visibility="visible" />
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
JSON ๋ฐ์ดํฐ๋ฅผ ํ์ฑํ๊ณ RecyclerView๋ก ํ์ํ๋ ๊ณผ์
- JSON ๋ฐ์ดํฐ ์์ ๋ฐ ํ์ฑ : ์๋ฒ์์ JSON ํ์์ ๋ฐ์ดํฐ๋ฅผ ์์ , ํ์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(Gson, Jackson ๋ฑ)๋ฅผ ์ฌ์ฉํ์ฌ JSON ๋ฐ์ดํฐ๋ฅผ ํ์ฑํ์ฌ Java ๊ฐ์ฒด๋ก ๋ณํ
- ์ด๋ํฐ ์์ฑ : RecyclerView.Adapter๋ฅผ ํ์ฅํ์ฌ ์ปค์คํ ์ด๋ํฐ๋ฅผ ๋ง๋ค๊ณ ์ด๋ํฐ ๋ด์์ ViewHolder ํด๋์ค๋ฅผ ์ ์ํ ํ, onBindViewHolder ๋ฉ์๋์์ ๋ฐ์ดํฐ๋ฅผ ๋ทฐ์ ๋ฐ์ธ๋ฉ
- RecyclerView ์ค์ : RecyclerView์ ๋ ์ด์์ ๋งค๋์ ๋ฅผ ์ค์ (์: LinearLayoutManager, GridLayoutManager ๋ฑ) ํ RecyclerView์ ์ด๋ํฐ๋ฅผ ์ค์
Json ๋ฐ์ดํฐ ํ์ฑํ๊ณ , ์ด๋ํฐ(adapter) ์ฌ์ฉํ์ฌ RecyclerView๋ก ๋ง๋ค๊ธฐ
JSON ๋ฐ์ดํฐ ํ์ฑํ๊ธฐ?
= ์ ์ด์จ์ผ๋ก ๋ฐ์์จ ๋ฐ์ดํฐ๋ฅผ ๊บผ๋ด์ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค. try ์์์ ์ฝ๋๋ฅผ ์ ๋ ฅํด์ผ ํ๋ค.
RecyclerView๋ Android์์ ๋๋์ ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ํ์ํ๊ธฐ ์ํ ๋ทฐ์ด๋ค. RecyclerView๋ ์คํฌ๋กค ์ ๋ทฐ๋ฅผ ์ฌ์ฌ์ฉ(recycle)ํ์ฌ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ค์ด๊ณ , ์ฑ๋ฅ์ ํฅ์์ํจ๋ค. ๋ํ ๋ค์ํ ๋ ์ด์์ ๋งค๋์ ๋ฅผ ํตํด ๋ฆฌ์คํธ, ๊ทธ๋ฆฌ๋, ์คํ๊ฑฐ๋ ๋ ์ด์์ ๋ฑ์ ์ฝ๊ฒ ๊ตฌํํ ์ ์์ผ๋ฉฐ ์ ๋๋ฉ์ด์ ์ง์ ๊ธฐ๋ฅ์ด ์๋ค.
์ด๋ํฐ(Adapter)๋ ๋ฐ์ดํฐ ์์ค(์: JSON ๋ฐ์ดํฐ)์ RecyclerView๋ฅผ ์ฐ๊ฒฐํ๋ ์ญํ ์ ํ๋ฉฐ ๋ฐ์ดํฐ ํญ๋ชฉ์ ๊ฐ๋ณ ๋ทฐ ํ๋(ViewHolder)์ ๋ฐ์ธ๋ฉํ์ฌ ๊ฐ ํญ๋ชฉ์ RecyclerView์ ํ์ํ๋ค.
๋จผ์ ์ด ๋ฐ์ดํฐ๋ฅผ,
{"status":"success","data":[{"id":1,"employee_name":"Tiger Nixon","employee_salary":320800,"employee_age":61,"profile_image":""},{"id":2,"employee_name":"Garrett Winters","employee_salary":170750,"employee_age":63,"profile_image":""},{"id":3,"employee_name":"Ashton Cox","employee_salary":86000,"employee_age":66,"profile_image":""},{"id":4,"employee_name":"Cedric Kelly","employee_salary":433060,"employee_age":22,"profile_image":""},{"id":5,"employee_name":"Airi Satou","employee_salary":162700,"employee_age":33,"profile_image":""},{"id":6,"employee_name":"Brielle Williamson","employee_salary":372000,"employee_age":61,"profile_image":""},{"id":7,"employee_name":"Herrod Chandler","employee_salary":137500,"employee_age":59,"profile_image":""},{"id":8,"employee_name":"Rhona Davidson","employee_salary":327900,"employee_age":55,"profile_image":""},{"id":9,"employee_name":"Colleen Hurst","employee_salary":205500,"employee_age":39,"profile_image":""},{"id":10,"employee_name":"Sonya Frost","employee_salary":103600,"employee_age":23,"profile_image":""},{"id":11,"employee_name":"Jena Gaines","employee_salary":90560,"employee_age":30,"profile_image":""},{"id":12,"employee_name":"Quinn Flynn","employee_salary":342000,"employee_age":22,"profile_image":""},{"id":13,"employee_name":"Charde Marshall","employee_salary":470600,"employee_age":36,"profile_image":""},{"id":14,"employee_name":"Haley Kennedy","employee_salary":313500,"employee_age":43,"profile_image":""},{"id":15,"employee_name":"Tatyana Fitzpatrick","employee_salary":385750,"employee_age":19,"profile_image":""},{"id":16,"employee_name":"Michael Silva","employee_salary":198500,"employee_age":66,"profile_image":""},{"id":17,"employee_name":"Paul Byrd","employee_salary":725000,"employee_age":64,"profile_image":""},{"id":18,"employee_name":"Gloria Little","employee_salary":237500,"employee_age":59,"profile_image":""},{"id":19,"employee_name":"Bradley Greer","employee_salary":132000,"employee_age":41,"profile_image":""},{"id":20,"employee_name":"Dai Rios","employee_salary":217500,"employee_age":35,"profile_image":""},{"id":21,"employee_name":"Jenette Caldwell","employee_salary":345000,"employee_age":30,"profile_image":""},{"id":22,"employee_name":"Yuri Berry","employee_salary":675000,"employee_age":40,"profile_image":""},{"id":23,"employee_name":"Caesar Vance","employee_salary":106450,"employee_age":21,"profile_image":""},{"id":24,"employee_name":"Doris Wilder","employee_salary":85600,"employee_age":23,"profile_image":""}],"message":"Successfully! All records has been fetched."}
์ด ์ฐฝ์ ์ด์ด ๋ฃ์ ํ, copy๋ฅผ ๋๋ฌ์ค๋ค.
https://jsoneditoronline.org/#left=local.tusimo&right=local.qofoce
์ค๊ดํธ {} ๋ object ๋ฐ์ดํฐ ํ์ ์ด๋ค.
๋๊ดํธ []๋ array ๋ฐ์ดํฐ ํ์ ์ด๋ค.
Adapter.java ํด๋์ค
(EmployeeAdapter.java๋ก ๋ง๋ค์ด์ฃผ์๋ค.)
package com.~.employee.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.~.employee.R;
import com.~.employee.model.Employer;
import java.text.DecimalFormat;
import java.util.ArrayList;
public class EmployerAdapter extends RecyclerView.Adapter<EmployerAdapter.ViewHolder> {
Context context;
ArrayList<Employer> employerArrayList;
public EmployerAdapter(Context context, ArrayList<Employer> employerArrayList) {
this.context = context;
this.employerArrayList = employerArrayList;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.employer_row, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Employer employer = employerArrayList.get(position);
holder.txtName.setText(employer.name);
holder.txtAge.setText(String.valueOf("๋์ด : "+employer.age+"์ธ"));
DecimalFormat formatter = new DecimalFormat("#,###");
String strSalary = formatter.format(employer.salary);
holder.txtSalary.setText(String.valueOf("์ฐ๋ด : $"+strSalary));
}
@Override
public int getItemCount() {
return employerArrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView txtName;
TextView txtAge;
TextView txtSalary;
ImageView imgDelete;
public ViewHolder(@NonNull View itemView) {
super(itemView);
txtName = itemView.findViewById(R.id.txtName);
txtAge = itemView.findViewById(R.id.txtAge);
txtSalary = itemView.findViewById(R.id.txtSalary);
imgDelete = itemView.findViewById(R.id.imgDelete);
}
}
}
MainActivity.java ํด๋์ค (ํ์ฑํ๊ธฐ)
package com.~.employee;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import com.yujinoh.employee.adapter.EmployerAdapter;
import com.yujinoh.employee.model.Employer;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
Button btnAdd;
ProgressBar progressBar;
EmployerAdapter adapter;
//๋ฆฌ์ฌ์ดํด๋ฌ๋ทฐ๋ ๊ด๋ จ๋ ๋ฉค๋ฒ๋ณ์ 2๊ฐ ๋ ์์ฑํด์ผ ํ๋ค
RecyclerView recyclerView;
ArrayList<Employer> employerArrayList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//๋ค์ ์ฝ๋๋ ์์ผ๋ก ๋ฌด์กฐ๊ฑด ๊ฐ์ด ์์ฑ
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
btnAdd = findViewById(R.id.btnAdd);
progressBar = findViewById(R.id.progressBar2);
recyclerView = findViewById(R.id.recyclerView);
btnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// AddActivity๋ฅผ ๋์ด๋ค
Intent intent = new Intent(MainActivity.this, AddActivity.class);
startActivity(intent);
}
});
// ๋คํธ์ํฌ๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์จ๋ค
// Volley ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํ ๋คํธ์ํฌ ํต์
// 1. request queue ๋ฅผ ๋ง๋ ๋ค
RequestQueue queue = Volley.newRequestQueue(MainActivity.this);
// 2. request(์์ฒญ)์ ๋ง๋ ๋ค.
// ๋ฐ์ดํฐ ํ์
์, ์๋ต์ json ํ์์ ๋ณด๊ณ ๊ฒฐ์ ํ๋ค.
JsonObjectRequest request = new JsonObjectRequest(
Request.Method.GET,
"https://block1-image-test.s3.ap-northeast-2.amazonaws.com/employees.json",
null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
// ํ๋ก๊ทธ๋ ์ค ๋ฐ๋ฅผ ์ ์ ์ ๋์์ ์ฌ๋ผ์ง๊ฒ ํ๋ ์ฝ๋
progressBar.setVisibility(View.GONE);
Log.i("EMPLOYEE MAIN", response.toString());
try {
String status = response.getString("status");
if(status.equals("success") == false){
Toast.makeText(MainActivity.this,
"๋คํธ์ํฌ ์๋ฌ",
Toast.LENGTH_SHORT).show();
return;
}
JSONArray data = response.getJSONArray("data");
for(int i = 0 ; i < data.length() ; i++){
JSONObject row = data.getJSONObject(i);
int id = row.getInt("id");
String name = row.getString("employee_name");
int salary = row.getInt("employee_salary");
int age = row.getInt("employee_age");
Employer employer= new Employer(id, name, salary, age);
employerArrayList.add(employer);
}
// ์ด๋ํฐ๋ฅผ ๋ง๋ค๊ณ
adapter = new EmployerAdapter(MainActivity.this, employerArrayList);
// ๋ฆฌ์ฌ์ดํด๋ฌ๋ทฐ์ ์ด๋ํฐ๋ฅผ ์ ์ฉํ๋ฉด ํ๋ฉด์ ๋์จ๋ค
recyclerView.setAdapter(adapter);
} catch (JSONException e) {
Toast.makeText(MainActivity.this,
"ํ์ฑ ์๋ฌ",
Toast.LENGTH_SHORT).show();
return;
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// ํ๋ก๊ทธ๋ ์ค ๋ฐ๋ฅผ ์ ์ ์ ๋์์ ์ฌ๋ผ์ง๊ฒ ํ๋ ์ฝ๋
progressBar.setVisibility(View.GONE);
Toast.makeText(MainActivity.this,
"๋คํธ์ํฌ ํต์ ์๋ฌ",
Toast.LENGTH_SHORT).show();
Log.i("EMPLOYEE MAIN", error.toString());
}
}
);
// 3. ๋คํธ์ํฌ๋ก ๋ณด๋ธ๋ค.
queue.add(request);
}
}
Employer.java ํด๋์ค
package com.~.employee.model;
public class Employer {
public int id;
public String name;
public int salary;
public int age;
public Employer(){
}
public Employer(int id, String name, int salary, int age) {
this.id = id;
this.name = name;
this.salary = salary;
this.age = age;
}
}