마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

리스트뷰 어댑터 질문있습니다.. (초보)

0 추천
저희 현재 상황은 어댑터(외부 클래스)는 따로 클래스로 정의하였고, 메인액티비티의 리스트뷰와 어댑터를 연결하여 addItem을 통해 총 4개의 아이템이 들어가있는 상황입니다.

근데 여기서 궁금한게  다른 액티비티에서 어댑터 객체를 만들어서 해당 액티비티의 리스트뷰와 연결하여  Main에 있는 4개의 아이템을 리스트뷰에 똑같이 갱신할 수 있는 방법이 있나요? 아니면 그대로 AddItem을 해줘야하나요.. 궁금합니다
로논 (360 포인트) 님이 2022년 1월 15일 질문

2개의 답변

+1 추천
리스트뷰나 어댑터가 아니라 데이터 자체를 공유하는 방향으로 생각을 해보시기 바랍니다. 화면에 보여지는 데이터가 있다면, 그건  그 데이터를 저장하고 있는 곳에서 부터 오는 데이터겠죠. 이걸 다른 화면과 공유하는 겁니다.

공유를 하는 수단으로는 상황에 따라 메모리, 파일, 데이터베이스 또는 서버 등을 사용할 수 있습니다. 님의 경우는 메모리가 우선 옵션일 것 같고, 파일 또는 데이터베이스도 고려해 볼 수는 있을 것 같습니다.

어떤 방법을 사용할 지는 님의 앱이 어떤 요구사항을 구현하고 있느냐에 따라 달라지게 됩니다. 단순히 화면간 데이터 공유를 원한다면 메모리를 사용하면 될 것 같고, 저장을 했다가 다음에 앱이 실행되고 나서도 보관되어야 하는 데이터라면 파일이나 데이터베이스를 생각해 볼 수 있을 것 같습니다.

가장 심플한 방법은 공유해야할 데이터가 크지 않다면 (500KB이하), Budle에 담아 다른 화면에 넘겨주면 됩니다. Bundle를 사용하는 방법은 액티비티와 프레그먼트가 약간씩 다릅니다. 액티비티의 경우는 Intent,  프레그먼트는  arguments를 통해 번들을 전달할 수 있습니다.

좀 더 구체적인 내용을 알고 싶다면, 질문을 좀 더 구체적으로 하시면 좋을 듯 합니다. 어떤 화면에서 어떤 호면으로 어떤 데이터가 넘어가는지와 위에서 말씀드린 요구사항 등등.
spark (226,420 포인트) 님이 2022년 1월 15일 답변
그렇군요, 데이터 자체를 공유하는 것이 좋은 거군요. 아직 데이터베이스까지 진도를 못 나가서 만약 있다면, 리스트뷰의 어댑터를 공유하는 방법이 가장 좋다고 생각을 했었습니다.


  adapter = new CommentAdapter();
        adapter.addItem(new CommentItem("dongeun12**",R.drawable.user1, (float) 5.1,"최고다."));
        adapter.addItem(new CommentItem("dongeun11**",R.drawable.user1,(float) 4.1,"재미잇다."));
        adapter.addItem(new CommentItem("dongeun34**",R.drawable.user1,(float) 2.1,"재미없었다."));

현재 MainActivity에서 위와 같이 아이템을 추가하고있고
allViewActivity에 똑같이 보여지고 싶습니다. 모두보기 버튼 클릭시 메모리 방식으로 allViewActivity로 인텐트로 데이터를 넘겨줘서 어댑터 형식으로 보여주면 되는건가요?
0 추천

데이터베이스를 사용하던 아니든 데이터를 저장하는 역할을 하는 인터페이스와 클래스를 만드세요. 우선은 메모리에만 데이터를 저장하도록 구현을 하시고 추후에 데이터베이스를 사용하게 되면 데이터베이스를 이용하는 클래스를 구현해서 고체하세요. 인터페이스이니까 아무 문제 없이 이게 가능합니다.

기본적인 아이디어를 보여 드릴게요.

// Review 클래스 정의. 
public class Review {
    private final float score;
    private final String comment;
    private final User user;
    
     //필요한 필드 정의
     // constructor, getter, setter 생략
}

public class User {
       
     //필요한 필드 정의
     // constructor, getter, setter 생략
}

// 데이터 조작에 필요한 동작을 정의하는 인터페이스 정의
public interface ReviewDataSource {
     List<Review> getReviews();
     Reivew getReviewById(String id);
     void addReview(Review review);
     void updateReview(Review review);
     void deleteReviewById9String id);
}

//.메모리를 사용하는 클래스 구현
public class ReviewMemoryDataSource implements ReviewDataSource {
     private List<Review> store = new ArrayList<>();  
   
     @Override
     public List<Review> getReviews() {
          return store;
     }
     
     // 다른 메소드들도 구현.
}

 

 이런 식으로 만드시고 사용하는 곳에서는 , 아래처럼 ReviewDataSource를 가져오는 팩토리를 하나만들고 ReviewDataSource  를 Singleton으로 만듧니다. ReviewDataSource 가 필요한 곳에서는  DataSorceFactory.getReviewDataSource()를 호출해서 사용합니다.

public class DataSorceFactory {
     private static ReviewDataSource reviewDataSource;
     public static ReviewDataSource getReviewDataSource() {
           if (reviewDataSource == null) {
                reviewDataSource = new ReviewMemoryDataSource();
           }
           
          return reviewDataSource;
     }    
}

 
public class MainActivity extends AppCompatActivity {

    private ReviewDataSource reviewDataSource;

    public void create(Bundle saveInstance) {
       super.create(saveInstance);
       this.reviewDataSource = DataSorceFactory.getReviewDataSource();
    }
   
}

 

추후에 데이터베이스로 전환하신다면 ReviewDataSource의 구현 클래스를 새로 만드시고 DataSourceFactory의 코드를 변경하시면 됩니다.

// DB를 사용하는 클래스 구현
public class ReviewDBDataSource implements ReviewDataSource {
     private SQLiteDatabase db = ...
   
     @Override
     public List<Review> getReviews() {
          ...
     }
     
     // 다른 메소드들도 구현.
}

public class DataSorceFactory {
     ...
     public static ReviewDataSource getReviewDataSource() {
          ..
                reviewDataSource = new ReviewDBDataSource();
          ...
     }    
}

이렇게 하면, ReviewDataSource를 사용하는 곳의 코드 변경없이 마이그레션이 가능합니다.

위의 예제에서는MainActivity의 DataSource, DataSource에 들어가는 ArrayList나  SQLite를 내부에서 생성했는데, 이 부분은 Dendency Injection이란 기법을 사용하는 것이 더 좋고, Dagger와 같은 라이브리러를 많이 사용합니다.

한가지 염두에 두실 점은 DataSource에서 사용하는 데이터의 구조와 화면에 필요한 데이터의 구조가 다르기 쉽다는 것입니다. 이건 DataSource에 있는 클래스의 인스턴스에 화면에 필요한 필드를 추가하지 마시고 화면용 클래스를 별도로 정의하셔서 화면에만 필요한 필드를 추가하세요. 그리고 데이터소스에서 가져온 데이터를 화면에 필요한 데이터로 매핑해서 상요하시기를 권장들려요. 이게 당장은 귀찮은 작업처럼 보이지만, 프로젝트가 진행이 되면 될 수록 얻는게 훨씬 많은 더 좋은 접근방법입니다. UI와 DataSource는 데이터든 클래스든 최대한 서로 분리하는게 좋습니다.

그리고 MainActivity 에제에서  DataSource를 바로 가져다 사용했는데, 이 부분도 중간에 DataSource와 뷰를 중계해줄 수 있는 중계클래스를 두는 것이 일반적입니다.(MVC, MVP, MVVM, MVI 패턴 중 하나 사용) 개발자라면, 반드시 그렇게 하시라고 말씀드리고 싶네요. (안 그러면 팀웤이 불가능할 수 있어요.)

spark (226,420 포인트) 님이 2022년 1월 16일 답변
spark님이 2022년 1월 16일 수정
...