2017-12-02 18 views
2

でシングルトンとしてRoomを使用するのに苦労しています。私はコトリンを使用します。SyncAdapterのシングルトンルームデータベースで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) 

のようなデータベースインスタンスを取得し、私の問題は、私はいつも私の活動にAppDatabaseSyncAdapterの2つの異なるインスタンスを取得することです。アクティビティAppDatabaseの中で実際にはシングルトン[email protected]であり、各onPerformSync()についてAppDatabaseはシングルトンすぎる[email protected]です。 しかし、あなたが見ることができるように、それらは2つの異なるオブジェクトです。 誰かが私がここでミスを説明することはできますか?

一方、私は達成しようとしていることで概念的に間違っているかもしれません。その後、アドバイスをいただければ幸いです。

新しいデータがリモートサーバーからSynAdapter経由で挿入されたときに、UIコンポーネントを更新することがポイントです。LiveDataを使用します。この場合、私はそれ以外の場合はトリガされません、新しい製品を挿入するにLiveDataをトリガするためにViewModel/Activityにし、SyncAdapterに同じproductDaoオブジェクトを使用する必要があります。 したがって、同じものを得るためには、productDaoと同じ(すなわち、シングルトン)を取得する必要がありますAppDatabase

私は、これは新しいデータを挿入する時に自動的にトリガされContentProviderを用いて実現することができることを知っています。しかし、私は本当に新しいandroidアーキテクチャのコンポーネントを試してみたい。 このユースケースを実装する唯一の正しい方法は、ContentProviderですか?

+0

あなたの 'SyncAdapter'はMainThreadと同じプロセスですか? (これはマニフェストで定義するものです) – MatPag

+0

いいえ、私のSyncAdapterはandroid:process = ":sync"を使用します。 シングルトンはプロセス間で共有されません。 – akamuza

+0

はい、それは「唯一の」問題かもしれません。 'process'行を削除して結果をここに戻してみましょう。 – MatPag

答えて

2

違うThreads間で簡単に通信をしたいときは、同じプロセスにする必要があります。 AndroidManifest.xmlあなたが属性を指定することができて

は、活動上(SyncAdaptersに関し)サービスコンテンツプロバイダあなたはヒープのデフォルトの限界を超えることができブロードキャストレシーバを、android:process=":processName"利用可能と呼ばれます(メモリ)を使用します。

ものですまとめPRO/CONS:

マルチプロセスのPRO:あなたはあなたのアプリケーションを実行するためのより多くのメモリを持っていると プロセスがクラッシュした場合、それは他のものをクラッシュしません。

マルチプロセスのCONS: それは相互に通信 プロセスをできるように、より多くの困難(しかし、不可能ではない)のですが、明らかにあなたは(あなたのケースで状態がシングルトンである)それらの間で状態を共有することはできません深い理解のために

、あなたはthis articlethis good answer

私の提案をお読みください:あなたのアプリがそれほど複雑ではないですし、私はあなたがで始まる示唆ますメモリの問題を持っていない場合単一のプロセスアプリローチ。一方、アプリケーションからデータを更新するSyncAdapterをデカップリングする場合や、開発中のある時点でシングルプロセスに関連するボトルネックやクラッシュが見つかった場合は、マルチプロセスに切り替え、直接LiveDataを削除し、ContentProviderを使用してデータの変更を通知します。

+0

しかし、それはどのようにアンドロイドが私のアプリケーションをシャットダウンする方法に影響を与えますか?私が意味することは、必要がない場合、アンドロイドが「重い」プロセスを殺す可能性があるということです。つまり、アプリを終了し、アンドロイドがしばらくそれを終了します。 しかし、SyncAdapterがアプリケーションが常駐する同じプロセスで実行されている場合、このプロセスは決して終了せず、アプリケーションは常にバックグラウンドでアクティブになりますか? – 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() 

} 

を:

@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彼は既にシングルトンパターンを正常に実装しましたが、彼の問題はSyncAdapterの2番目のプロセスの使用に関連していました。 Daggerはこの特定の問題の解決策ではありません(おそらくDaggerが単一シングルトンのすべての複雑さを必要としないため) – MatPag

関連する問題