Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

create method of DataSource.Factory doesn't get call

Im trying to make a dictionary application with Paging library. when a user writes any letters, I will call an API and get all the words including that letter.

The problem is that, when I call the API via the Paging library in the init{} method of my ViewHolder, it works perfectly. but after that, when I try to write something else and get relevant data, Paging library doesn't even call the API. I put breakpoints every where, and I saw that after the first time, the create() method of DataSource.Factory doesn't get call.

here is my code :

My Activity :

    viewModel = ViewModelProviders.of(this).get(DictionaryViewModel::class.java)
    val adapter = DictionaryRecyclerPagedAdapter()
    recycler.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
    recycler.setHasFixedSize(true)
    recycler.adapter = adapter

    RxTextView.textChanges(edtWord)
        .filter { it.isNotBlank() }
        .subscribe({
            adapter.submitList(null)
            viewModel.getWord(it.toString())
            Logger.d(it)

        }, {
            Logger.d(it)
        })



    viewModel.itemPagedList?.observe(this, Observer {
        adapter.submitList(it)
    })

My ViewModel :

var liveDataSource: LiveData<PageKeyedDataSource<Int, DictionaryResult>>? = null
var itemPagedList: LiveData<PagedList<DictionaryResult>>? = null

init {

    getWord("pouya")
}

fun getWord(term: String) {

    val dataSourceFactory = DictionaryDataFactory(term)
    liveDataSource = dataSourceFactory.liveData


    val config = PagedList.Config.Builder()
        .setEnablePlaceholders(true)
        .setPageSize(10)
        .setPrefetchDistance(4)
        .build()

    itemPagedList = LivePagedListBuilder(dataSourceFactory, config).build()

}

My DataSource :

   class DictionaryDataSource(private val term: String) : PageKeyedDataSource<Int, DictionaryResult>() {

override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, DictionaryResult>) {
    Logger.d("Initial")
    composite.add(
        repository.getWord(FIRST_PAGE, term)
            .subscribe({
                if (it.result != null)
                    callback.onResult(it.result, null, FIRST_PAGE + 1)
            }, {
                Logger.d(it)

            })
    )
}

override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, DictionaryResult>) {
    Logger.d("AFTER")
    composite.add(repository.getWord(params.key, term)
        .subscribe({
            if (it.result != null)
                callback.onResult(it.result, params.key + 1)
        }, {
            Logger.d(it)
        })
      )

    }

}

My DataSource.Factory :

  class DictionaryDataFactory(private val term: String) : DataSource.Factory<Int, DictionaryResult>() {

val liveData = MutableLiveData<PageKeyedDataSource<Int, DictionaryResult>>()

override fun create(): DataSource<Int, DictionaryResult> {
    val dataSource = DictionaryDataSource(term)
    liveData.postValue(dataSource)
    return dataSource
    }
 }

So just have this in mind that it works perfectly as soon as I launch the app (it gets all the meanings for the word "pouya" as I called it in init{} method of my ViewHolder) but afterward, when I write something in the edittext, all the needed methods get called, except create() method of DataSource.Factory.

any helps would be appreciated.

like image 451
Pouya Heydari Avatar asked May 05 '19 15:05

Pouya Heydari


1 Answers

I have faced the same problem , what solved it for me was to build the list before setting observers , in your case make sure getWord() is called before itemPagedList is observed on

For example :- Here's a snippet from a fragment which uses viewModel.reponseList

override fun onViewReady() {
    setRecyclerView()
    viewModel.buildResponseList() //For some reason responseList must be built before observing on it ,
    // otherwise create() in FoodDataSourceFactory won't be called
    setObservers()
}

private fun setObservers() {
    viewModel.responseList.observe(this, Observer {
        (this.rvFoodList.adapter as FoodListAdapter).submitList(it)
    })
}

private fun setRecyclerView() {
    val mRecyclerView = this.rvFoodList
    mRecyclerView.apply {
        layoutManager = LinearLayoutManager([email protected])
        adapter = FoodListAdapter()
    }

ViewModel Part : -

fun buildResponseList() {
    val foodDataSourceFactory =
        FoodDataSourceFactory(this)

    val config = PagedList.Config.Builder()
        .setInitialLoadSizeHint(30)
        .setEnablePlaceholders(false)
        .setPageSize(30)
        .build()

    responseList = LivePagedListBuilder(foodDataSourceFactory, config).build()
}

in onViewReady()

if I setObservers() before I call viewModel.buildResponseList()

DataSourceFactory class won't call create() method thus not making network call in DataSource class

like image 143
Khaled Ahmed Avatar answered Oct 25 '22 10:10

Khaled Ahmed