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

Room 데이터 다른 클래스에서 사용 (java)

0 추천

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private Connection connection;
    public FoodDao mFoodDao;

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

        DataBase database = Room.databaseBuilder(getApplicationContext(), DataBase.class, "food_db")
                .fallbackToDestructiveMigration()
                .allowMainThreadQueries()
                .build();

        mFoodDao = database.foodDao();
        
        List<Food> foodList = mFoodDao.getFoodAll();
        for (int i = 0; i < foodList.size(); i++) {
            Log.d("TEST", foodList.get(i).getName() + "\n"
                    + foodList.get(i).getSpicy() + "\n"
                    + foodList.get(i).getSoup() + "\n"
                    + foodList.get(i).getRice() + "\n"
                    + foodList.get(i).getNoodle() + "\n"
                    + foodList.get(i).getOily() + "\n"
                    + foodList.get(i).getBread() + "\n"
                    + foodList.get(i).getHungry() + "\n");
        }
    }
}

Dao.java

@Dao
interface FoodDao {

    @Insert
    void setInsertFood(Food food);

    @Update
    void setUpdateFood(Food food);

    @Delete
    void setDeleteFood(Food food);

    @Query("SELECT * FROM Food")
    List<Food> getFoodAll();
}

DataBase.java

@Database(entities = {Food.class}, version = 1)
public abstract class DataBase extends RoomDatabase {
    public abstract FoodDao foodDao();


}

 

안드로이드를 자바 언어로 구현 중인데 어딜 찾아봐도 mainactivity가 아닌 다른 클래스에서 디비 내용 활용하는 방법을 못찾았어요. mFoodDao를 public으로 해보고 다른 클래스에서 사용하려고 해봐도 다른 클래스에서 조회를 해보면 로그캣에 테스트값이 출력되지 않아요. 데이터베이스에 값은 insert가 다 되어있구요.

Dao에서 @Query()를 통해 저장된 값을 다른 클래스에서 사용하는 방법좀 알려주시면 감사드립니다!

rrrrsu (150 포인트) 님이 2022년 6월 2일 질문

1개의 답변

0 추천
 
채택된 답변

Activity에서는 화면을 업데이트하는 기능이외의 일, 특히 IO관련 작업을 하는 건 다른 책임을 섞게 되므로, 코드의 readability(가독성), maintenance(유지보수) 등의 측면에서 좋지 않습니다. 예를 들면, 화면 업데이트 관련 변경시에도 DB 관련 코드가 같이 들어가 있는 액티비티를 건드려야 하고, DB관련 로직 수정시에도 다시 액티비티를 건드려야 하므로, 수많은 이유로 액티비티를 건드려야 하기 때문에 한가지 기능을 가진 클래스를 별도로 가지는 것보다 많이 복잡한 코드가 됩니다.

Google의 Room DB 라이브러리 개발자가 올려놓은 샘플코드 참조하세요.

https://github.com/googlecodelabs/android-room-with-a-view

 

그리고 님이 겪는 문제는 Database 인스턴스가 하나가 아니라서 그런 것 같습니다. 님처럼 액티비티에서 직접 Database객체에 접근하려면 아래처럼 Singleton을 만드셔야 할 것 같네요.

@Database(entities = ...)
public abstract Database extends RoomDatabse {

    private static Database instance;
    public static synchronized Database getInstance(Context context) {
        if (instance == null)
            instance = Room.databaseBuilder(context.getApplicationContext(), Database.class);
                        .build();
        return instance;
    }

    public abstract FoodDao foodDao();
}


public class MainActivity extends AppCompatActivity {;
    private FoodDao mFoodDao;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        
        mFoodDao = Database.getInstance(this).foodDao();
         ...
    }

   
}

 

그렇지 않으면 Application 클래스를 만들어서 여기에서 Database를 초기화고 이 인스턴스를 공유할 수도 있을 것 같구요.

 

spark (226,420 포인트) 님이 2022년 6월 2일 답변
rrrrsu님이 2022년 6월 7일 채택됨
참고로 Database초기화하는 코드는 Application 클래스로 옮기시는게 좋습니다.

DataBase database = Room.databaseBuilder(getApplicationContext(), DataBase.class, "food_db")
                .fallbackToDestructiveMigration()
                .allowMainThreadQueries()  //<---
                .build();

그리고 빌더에 allowMainThreadQueries는 제거하시고 메인쓰레드말고 백그라운드 쓰레드에서 DB를 처리를 하는게  보통을 방식입니다. DB, File, Server API 호출 등등은 IO 오퍼레이션이므로 특별한 이유가 있지 않으면 앱은 가능하면 UI를 블락하지 않도록 백그라운드 쓰레등에서 치리하는 것이 모바일 개발의 원칙입니다.
...