2017-01-29 1 views
1

私はAndroidアプリを書く経験はあまりありません。楽しみのため私は私のサーバーに私の通話記録をアップロードするアプリを書いています。このアプリ全体がサービスとして実行されています。 ContentObserverを登録したサービスは、電話機が起動したときに起動するサービスで、私のカスタムCallLogクラスが呼び出されます。私はContentObserverを使用して、コンテンツ変更イベントを待ち受けます。残念なことに、ContentObserverは複数回呼び出されます。番号をダイヤルします。古くなったデータを返す領域

そのため、markAsUploaded()というアップロードが成功した(私はRetrofitを使用した)後に呼び出すという機能があります。この関数はCallLogUploadedと呼ばれるRealmObjectを作成します(これは私の普通のCallLogモデルとは異なります)。このCallLogUploadedには、コールのdateTimeという1つの識別子があります。これは十分にユニークである必要があります。次に、すべてのコールログのリストを繰り返しているときに、すべてのコールログをisDataUploaded()関数と照合してレルムクエリを実行し、そのdateTimeを持つコールログがデータベースに格納されているかどうかを確認します領域)。理論的にはうまくいくはずです。

しかし、私はそれが必ずしも機能しないことに気がつきました。非常に頻繁に私のデータが古くなっているようです。 realm.isAutoRefresh()を実行すると、falseを返します(私はそれが一度trueを返すと宣言します)。私のisDataUploaded機能では、私がレルム上でfindAll()を実行しても、すべてのデータが表示されませんが、データは確かにmarkDataAsUploadedの機能に当たっていました。

val callLogCall = service.sendCalLLogs(childId, dataToUpload) 
    callLogCall.enqueue(object : Callback<Void> { 
     override fun onResponse(call: Call<Void>, response: Response<Void>) { 
      if (response.isSuccessful) { 
       Log.i(AppConstants.LOG_TAG, "Call log data uploaded successfully!") 
       [email protected](dataToUpload) 
      } else { 
       Log.w(AppConstants.LOG_TAG, "Call log data upload failed") 
      } 
     } 

     override fun onFailure(call: Call<Void>, t: Throwable) { 
      Log.w(AppConstants.LOG_TAG, "Call log data upload error (onFailure) called") 
     } 
    }) 


// This function simply stores a Realm model for all the data that has been uploaded to the server 
private fun markDataAsUploaded(dataToUpload: List<CallLog>) { 
    realm = Realm.getDefaultInstance() 
    for (data in dataToUpload) { 
     realm.beginTransaction() 
     val callLogUploaded = realm.createObject(CallLogUploaded::class.java) 
     callLogUploaded.callDate = data.callDate 

     realm.commitTransaction() 
    } 
} 

// This function checks to see if the data is already uploaded. 
private fun isDataUploaded(callLog: CallLog) : Boolean { 
    return realm 
      .where(CallLogUploaded::class.java) 
      .equalTo("callDate", callLog.callDate) 
      .count() > 0L 
} 

// Gets the call logs - not the entire function 
for (call in callLogs) { 
    val callLog = CallLog() 
    callLog.id = call.id 
    callLog.callDate = Utilities.getTimestampAsSeconds(call.callDate) 

    if (this.isDataUploaded(callLog)) { 
     continue 
    } 

    callLog.name = call.name 
    callLog.number = call.number 
} 

私はレルムに非常に新しく、Androidの開発にかなり新しいですので、私はあなたが私を与えることができます任意の助けをいただければ幸いです:それはKotlinにですが、理解しやすいべきである -

は、ここに私のコードです。ありがとう!

答えて

1

// This function simply stores a Realm model for all the data that has been uploaded to the server 
private fun markDataAsUploaded(dataToUpload: List<CallLog>) { 
    realm = Realm.getDefaultInstance() 
    for (data in dataToUpload) { 
     realm.beginTransaction() 
     val callLogUploaded = realm.createObject(CallLogUploaded::class.java) 
     callLogUploaded.callDate = data.callDate 

     realm.commitTransaction() 
    } 
} 

このメソッドは、レルムのインスタンスが開かれたquite a few errors that I had written about a long time ago

  • を持っているためだが、

  • 新しいすべての要素ごとのトランザクションではなく、挿入はありを閉じないこと単一の取引のすべての要素

Realmインスタンスを閉じないと(各インスタンスで独自のclose()コールが必要な場合)、Realmインスタンスは実際にトランザクションを開始してトランザクション内で操作しない限り更新されません。

次の3つのソリューションを持っている:

1)が行われるべきものがない場合は、トランザクション内のバックグラウンドスレッドで、あなたのロジックを行い、その後、トランザクションを取り消す - 取引で行われたクエリは

古くなることはありません

2.)Realmインスタンスが正しく閉じられていることを確認します(これは、自動更新を行わないスレッドでは絶対必要です)。

3。)ハックソリューションは、通常、あなたがスレッドの最初にレルムインスタンスを開く必要がありRealmRefresh.refreshRealm() after getDefaultInstance() according to my answer on Stack Overflow which relies on package-private API, but it works to solve this issue


呼び出し、スレッドの終了時に、それを閉じることです。

ですので、の場合、基本的には1つの大きなtry(Realm realm = Realm.getDefaultInstance() { ... }です。 UIスレッド上


enqueue(new Callback() { @Override public void onSuccess(..) {...}実行されます。現在のスレッドで実行するには、call.execute()を使用してください。


代わりの

for (data in dataToUpload) { 
    realm.beginTransaction() 
    val callLogUploaded = realm.createObject(CallLogUploaded::class.java) 
    callLogUploaded.callDate = data.callDate 

    realm.commitTransaction() 
} 

あなたがhttps://medium.com/@Zhuinden/understanding-realm-version-retention-and-synchronization-9a513c2445bbを読むことができるバージョンの保持について理解するためには

realm.beginTransaction() 
for (data in dataToUpload) { 
    val callLogUploaded = realm.createObject(CallLogUploaded::class.java) 
    callLogUploaded.callDate = data.callDate 
} 
realm.commitTransaction() 

を行います。

関連する問題