제가 테스트해 본 소스코드를 올릴게요. 코드가 완전히 정리된 코드는 아니지만, 로직을 보시는데는 별 문제 없으실 거예요. 제 코드에는 포함시키지는 않았지만, 데이터를 처리하는 로직의 분리와 에러핸들링의 경우도 고려하시면 좋을 것 같아요.
Github에 해당 소스를 올려놨으니까, 이메일을 알려주시면 리포를 볼 수 있도록 해드리겠습니다.
import java.io.Serializable;
public class Artwork implements Serializable {
private String itemId;
private String artName;
private String artist;
private String image;
private int price;
public Artwork() {
}
public Artwork(String itemId, String artName, String artist, String image, int price) {
this.itemId = itemId;
this.artName = artName;
this.artist = artist;
this.image = image;
this.price = price;
}
public String getItemId() {
return itemId;
}
public void setItemId(String itemId) {
this.itemId = itemId;
}
public String getArtName() {
return artName;
}
public void setArtName(String artName) {
this.artName = artName;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
public class ArtworkListActivity extends AppCompatActivity {
public final static String ARTWORKS_REF_NAME = "Itemlist";
private ActivityArtworkListBinding binding;
private ArtworkAdapter artworksAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityArtworkListBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
viewDidLoad();
loadArtworks();
}
private void viewDidLoad() {
artworksAdapter = new ArtworkAdapter();
artworksAdapter.setListener(new ArtworkAdapter.Listener() {
@Override
public void onArtworkClicked(Artwork artwork) {
artworkClicked(artwork);
}
});
binding.artworksRcv.setAdapter(artworksAdapter);
}
private void artworkClicked(Artwork artwork) {
Intent intent = ArtworkActivity.artworkIntent(this, artwork);
startActivity(intent);
}
private void loadArtworks() {
binding.loadingIndicator.show();
FirebaseDatabase database = FirebaseDatabase.getInstance();
database.getReference(ARTWORKS_REF_NAME)
.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
dataFetched(snapshot);
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
}
private void dataFetched(@NonNull DataSnapshot dataSnapshot) {
List<Artwork> artworks = new ArrayList<>();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Artwork artwork = snapshot.getValue(Artwork.class);
assert artwork != null;
artwork.setItemId(snapshot.getKey());
artworks.add(artwork);
}
runOnUiThread(() -> {
artworksAdapter.submitList(artworks);
binding.loadingIndicator.hide();
});
}
}
public class ArtworkAdapter extends RecyclerView.Adapter<ArtworkViewHolder> {
interface Listener {
void onArtworkClicked(Artwork artwork);
}
private List<Artwork> items = new ArrayList<>();
private Listener listener;
public void setListener(Listener listener) {
this.listener = listener;
}
public void submitList(List<Artwork> items) {
this.items = items;
notifyDataSetChanged();
}
@Override
public int getItemCount() {
return items.size();
}
@NonNull
@Override
public ArtworkViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_artwork, parent, false);
return new ArtworkViewHolder(itemView, listener);
}
@Override
public void onBindViewHolder(@NonNull ArtworkViewHolder holder, int position) {
Artwork artwork = getItem(position);
holder.bind(artwork);
}
private Artwork getItem(int position) {
return items.get(position);
}
}
public class ArtworkViewHolder extends RecyclerView.ViewHolder {
private final ItemArtworkBinding binding;
private ArtworkAdapter.Listener listener;
public ArtworkViewHolder(@NonNull View itemView, ArtworkAdapter.Listener listener) {
super(itemView);
binding = ItemArtworkBinding.bind(itemView);
this.listener = listener;
}
public void bind(Artwork artwork) {
Glide.with(binding.artworkImage)
.load(artwork.getImage())
.into(binding.artworkImage);
binding.nameText.setText(artwork.getArtName());
binding.priceText.setText(String.valueOf(artwork.getPrice()));
itemView.setOnClickListener(v -> {
listener.onArtworkClicked(artwork);
});
}
}
public class ArtworkActivity extends AppCompatActivity {
private static final String EXTRA_ARTWORK = "artwork";
public static Intent artworkIntent(Context context, Artwork artwork) {
Intent intent = new Intent(context, ArtworkActivity.class);
intent.putExtra(EXTRA_ARTWORK, artwork);
return intent;
}
private ActivityArtworkBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityArtworkBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
viewDidLoad();
}
private void viewDidLoad() {
Artwork artwork = (Artwork) getIntent().getSerializableExtra(EXTRA_ARTWORK);
loadArtwork(artwork);
}
// 파이어베이스에서 데이터를 다시 가져오지 않고 이전 액티비티에서 전달받은 Artwork 인스턴스만으로 화면에 데이터를 표시하는 것만으로
// 충분하다고 판단될 경우는 파이어베이스를 호출할 필요가 없음.
private void loadArtwork(Artwork artwork) {
FirebaseDatabase database = FirebaseDatabase.getInstance();
database.getReference(ARTWORKS_REF_NAME)
.child(artwork.getItemId())
.get()
.addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
@Override
public void onComplete(@NonNull Task<DataSnapshot> task) {
if (!task.isSuccessful()) {
artworkLoadFailure(task.getException());
return;
}
artworkLoadSuccess(task);
}
});
}
private void artworkLoadSuccess(@NonNull Task<DataSnapshot> task) {
Artwork artwork = Objects.requireNonNull(task.getResult()).getValue(Artwork.class);
assert artwork != null;
bindArtwork(artwork);
}
private void bindArtwork(Artwork artwork) {
Glide.with(binding.artworkImage)
.load(artwork.getImage())
.into(binding.artworkImage);
binding.nameText.setText(artwork.getArtName());
binding.priceText.setText(String.valueOf(artwork.getPrice()));
}
private void artworkLoadFailure(Exception exception) {
// 에러 처리할 것
}
}
레이아웃 파일과 빌드파일은 별도로 올리지 않겠습니다.