2017-12-02 10 views
2

에 싱글 톤으로 Room을 사용하는 데 어려움을 겪고 있습니다. 나는 코 틀린을 사용한다.SyncData의 Singleton Room 데이터베이스가 LiveData를 트리거합니다.

내 방 클래스는

@Database(entities = [(Product::class)], version = 1, exportSchema = false) 
abstract class AppDatabase : RoomDatabase() { 
    abstract fun productDao(): ProductDao 

    companion object { 
     @Volatile private var INSTANCE: AppDatabase? = null 

     fun getInstance(context: Context) : AppDatabase = 
      INSTANCE ?: synchronized(this) { 
       INSTANCE ?: buildDatabase(context.applicationContext) 
         .also {INSTANCE = it} 
      } 

     private fun buildDatabase(context: Context) = 
       Room 
         .databaseBuilder(context.applicationContext, 
           AppDatabase::class.java, "database.db") 
         .allowMainThreadQueries() 
         .build() 
    } 

} 

나는이

val db = AppDatabase.getInstance(applicationContext) 

같은 데이터베이스 인스턴스를 검색 그리고 내 문제는 내가 항상 내 활동과 SyncAdapterAppDatabase의 두 개의 서로 다른 인스턴스를 얻을 수 있다는 것입니다. 액티비티 중 AppDatabase이 실제로 싱글 톤 [email protected]이고 각 onPerformSync()에 대해 AppDatabase도 싱글 톤이 [email protected]입니다. 그러나 보시다시피 두 개의 다른 개체입니다. 아무도 내가 여기에서 놓친 것을 설명 할 수 있습니까?

반면에 내가 어쩌면 내가 개념적으로 달성하려고 시도하는 것이 잘못되었습니다. 그럼 모든 조언을 주시면 감사하겠습니다.

요점은 SynAdapter을 통해 원격 서버에서 새 데이터를 삽입 할 때 LiveData을 사용하여 UI 구성 요소를 업데이트하는 것입니다. 이 경우 새 제품을 삽입 할 때 LiveData를 트리거하기 위해 동일한 productDao 개체를 ViewModel/ActivitySyncAdapter에 사용해야합니다. 그렇지 않으면 트리거되지 않습니다. 따라서 동일한 것을 얻으려면 productDao 동일해야합니다 (즉, 싱글 톤) AppDatabase.

이것은 새로운 데이터 삽입시 자동으로 실행되는 ContentProvider을 사용하여 구현할 수 있음을 알고 있습니다. 하지만 실제로 새로운 안드로이드 아키텍처 구성 요소를 사용해보고 싶습니다. ContentProvider을 사용하는 것이이 유스 케이스를 구현하는 유일한 올바른 방법일까요?

+0

'SyncAdapter'는 MainThread와 동일한 프로세스입니까? (이것은 매니페스트에서 정의한 것입니다.) – MatPag

+0

아니요, 내 SyncAdapter는 android : process = ": sync"를 사용합니다. 내가 무슨 뜻인지 알 것 같네. 싱글 톤은 프로세스간에 공유되지 않습니까? – akamuza

+0

예, "유일한"문제 일 수 있습니다. 'process' 라인을 제거하고 결과를 여기에 게시 해 봅시다. – MatPag

답변

2

당신은 동일한 프로세스에서해야합니다. AndroidManifest.xml 당신이 속성을 지정할 수 있습니다에서

는 힙의 기본 한도를 초과 도움이 될 수있는, 활동, 서비스을 (SyncAdapters 관련), 정보 제공자방송 수신기에 사용할 수 android:process=":processName"라고 (메모리).

그있는 요약 PRO/CONS :

멀티 프로세스 PRO : 당신은 당신의 응용 프로그램을 실행하는 데 더 많은 메모리를 가지고 있고 프로세스가 충돌하는 경우는 다른 사람을 충돌하지 않습니다.

멀티 프로세스 CONS : 이 서로 통신 프로세스를 수 있도록 더 많은 어려운 (그러나 불가능)입니다하지만 분명히 당신은 (귀하의 경우 상태가 싱글 톤) 그 사이에 상태를 공유 할 수 없습니다 앱이 너무 복잡하지 않고 당신이 메모리에 문제가없는 경우 난 당신과 함께 시작하는 것이 좋습니다 것이다 :

깊은 이해를 위해, 당신은 this articlethis good answer

나의 제안 읽어야 단일 프로세스 앱 바퀴벌레. 앱에서 데이터를 업데이트하는 SyncAdapter를 분리하려는 경우 또는 단일 프로세스와 관련된 병목 현상이나 충돌을 발견 한 시점에서 다중 프로세스로 전환하고 직접 LiveData를 제거하고 ContentProvider를 사용하여 데이터 변경을 알린다.

+0

하지만 안드로이드가 내 응용 프로그램을 종료하는 방법에 어떤 영향을 줍니까? 내 말은 안드로이드가 필요하지 않다면 안드로이드가 "무거운"프로세스를 죽일 수 있다는 것입니다. 즉, 내 앱을 종료하고 언젠가는 안드로이드가 잠시 죽이면됩니다. 그러나 내 SyncAdapter가 Application이있는 동일한 프로세스에서 실행되는 경우이 프로세스가 절대 종료되지 않고 내 앱이 항상 백그라운드에서 활성화된다는 것을 의미합니까 ?? – akamuza

+0

어쨌든 나는 당신의 대답을 받아들입니다. 너 나 많이 도와 줬어. 고마워. 자세한 논의는 거래를 완전히 이해하기위한 것입니다. – akamuza

+1

이것은 실제로 당신의 필요에 달려 있습니다. SyncAdapter에서 LiveData 기능을 사용하려면 SyncAdapter를 동일한 프로세스에 배치해야합니다. 시스템에서 앱을 종료하지 못하게하려면 다중 프로세스 접근 방식을 사용하고 콘텐츠 제공 업체를 통해 데이터에 액세스 할 수 있습니다. 내가 말했듯이 이것은 당신이 당신의 응용 프로그램으로 무엇을 이루고자 하는가에 달려있다. – MatPag

0

사용 dagger2 : 활동에서

class MyApplication : Application(){ 

    val component: AppComponent by lazy { 
     DaggerAppComponent.builder().appModule(AppModule(this)).build() 
    } 

    @Inject 
    lateinit var database : AppDatabase 

    override fun onCreate() { 
     super.onCreate() 
     component.inject(this) 
    } 

} 
@Singleton 
@Component(modules = arrayOf(
     AppModule::class 
)) 
interface AppComponent { 
    fun inject(app: MyApplication) 
} 

@Module 
class AppModule constructor(private val context: Context) { 

@Provides 
@Singleton 
fun providesDatabase() = Room.databaseBuilder(context, AppDatabase::class.java, "mydb.db").build() 

} 

: 당신이 다른 Threads 사이에 쉽게 의사 소통을 할 때

@Inject lateinit var mRoomDatabase: AppDatabase 

override fun onCreate(savedInstanceState: Bundle?) { 
    super.onCreate(savedInstanceState) 
    (application as MyApplication).component.inject(this) 
} 
+0

Dagger2를 사용해 보았습니다.하지만 초보자인데 너무 압도적이었습니다. 주된 문제는 AppDatabase를 삽입 할 수 없다는 것입니다. 'SyncAdapter'. 그럼, 어떻게 설명 할 수 있나요, 제발, 어떻게'SyncAdapter'에 주사 할 수 있습니다. – akamuza

+0

잘 이해했다면, 싱글 톤 데이터베이스가 필요하고 아키텍처 구성 요소를 사용하여 DAO 클래스의 변경 사항을 듣고 관련 어댑터를 자동으로 새로 고치시겠습니까? – sokarcreative

+1

@sokarcreative 그는 이미 Singleton 패턴을 성공적으로 구현했으며, 그의 문제는 SyncAdapter에 두 번째 프로세스를 사용하는 것과 관련이 있습니다. Dagger는이 특정 문제에 대한 해결책이 아닙니다. (아마도 Dagger가 단일 Singleton을 위해 가져야 할 모든 복잡성을 필요로하지 않기 때문입니다.) – MatPag