Search code examples
androidkotlinstoreandroid-room

Having trouble fetching data using android nytimes Store library


I have the following code, that i'm trying to use to fetch data from an API endpoint using the NyTimes/Store library to cache it

I'm using DI to load my dependencies as follows

  val appModule = module(override = true) {
        single<MyAppDatabase> {
            Room.databaseBuilder(androidApplication(), MyAppDatabase::class.java, "MJiraniRoomDB")
                .fallbackToDestructiveMigration()
                .build()
        }
        //DATABASE ACCESS OBJECTS
        factory<BlogDao> { get<MyAppDatabase>().blogDao() }
        factory<BlogLocalService> { BlogLocalService(get()) }
        factory<BlogRemoteService> { BlogRemoteService(get()) }
        factory<BlogStore> { BlogStore(get(), get()) }

The service where i use the Store library with RoomStore is here

package com.example.myapplication.service.BlogService

import com.example.myapplication.model.Blog
import com.nytimes.android.external.store3.base.Fetcher
import com.nytimes.android.external.store3.base.impl.BarCode
import com.nytimes.android.external.store3.base.impl.MemoryPolicy
import com.nytimes.android.external.store3.base.impl.StalePolicy
import com.nytimes.android.external.store3.base.impl.room.StoreRoom
import com.nytimes.android.external.store3.base.room.RoomPersister
import io.reactivex.Observable
import java.util.concurrent.TimeUnit

class BlogStore(val blogRemoteService: BlogRemoteService, val blogLocalService: BlogLocalService) {

    var fetcher = Fetcher<List<Blog>, BarCode> {
        blogRemoteService.fetchBlogs()
    }

    val persister = object : RoomPersister<List<Blog>, List<Blog>, BarCode> {

        override fun read(barCode: BarCode): Observable<List<Blog>> {
            return blogLocalService.fetchAll().toObservable()
        }

        override fun write(barCode: BarCode, blogList: List<Blog>) {
            blogLocalService.addBlogs(blogList)
        }
    }

    var memoryPolicy: MemoryPolicy = MemoryPolicy
        .builder()
        .setExpireAfterWrite(5)
        .setExpireAfterTimeUnit(TimeUnit.SECONDS)
        .build()

    var store = StoreRoom.from(fetcher, persister, StalePolicy.REFRESH_ON_STALE, memoryPolicy)

    fun getBlogs(): Observable<List<Blog>> {
        store.clear()
        return store.fetch(BarCode.empty())
    }
}

I pull the data to my Recyclerview as follows

class RemotePostsFragment : Fragment() {
    val scopeProvider by lazy { AndroidLifecycleScopeProvider.from(this) }

    val myBlogStore: BlogStore by inject()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        var mRecyclerview = view.findViewById<RecyclerView>(R.id.myRemoteViewRecycler)


        var theAdapter = MyAdapter()
       myBlogStore.getBlogs()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .autoDisposable(scopeProvider)
            .subscribe({ bloglist ->
                theAdapter.blogItems = bloglist
            }, {
                Log.e("RemotePostFragment", "failed got message ${it.message}")
            })


        mRecyclerview.adapter = theAdapter
        mRecyclerview.layoutManager = LinearLayoutManager(this.context)
    }

The problem is that i only load the data from the android room db but its never fetched from the server. When i do the raw query from the server that's used from the fetcher, i'm able to get a List of Blogs. But when i use it in the Fetcher, i'm not able to automatically sync.

My blogRemoteService returns a Single> correctly when tested on its own. What could i be doing wrong?


Solution

  • I found out the solution to my problem, in my RoomPersister in the write method i was passing blogLocalService.addBlogs(blogList) which returns a Single<List<Blog>> which I forgot to subscribe to. This is what i had previously

    val persister = object : RoomPersister<List<Blog>, List<Blog>, BarCode> {
    
            override fun read(barCode: BarCode): Observable<List<Blog>> {
                return blogLocalService.fetchAll().toObservable()
            }
    
            override fun write(barCode: BarCode, blogList: List<Blog>) {
                blogLocalService.addBlogs(blogList)
            }
        }
    

    I wrongly assumed that the Singe>> method would somehow automatically get subscribbed to. This was my final code that worked

    val persister = object : RoomPersister<List<Blog>, List<Blog>, BarCode> {
    
            override fun read(barCode: BarCode): Observable<List<Blog>> {
                return blogLocalService.fetchAll().toObservable()
            }
    
            override fun write(barCode: BarCode, blogList: List<Blog>) {
                blogLocalService.addBlogs(blogList).
                .subscribeOn(Schedulers.io())
                        .observeOn(Schedulers.io())
                        .subscribe({
                        Log.d("BlogLocalService","successful write to db")
                    },{
                        Log.d("BlogLocalService","failed to write to db with error: ${it.message}")
                    })
            }
        }