I am having a problem where Each time the system updates from the service, the new items are placed before the item that the recycler is at. This means that it will always be at "the end". I am using the PagedList.BoundaryCallback library and I don't know hot to fix this.
This is my RepoBoundaryCalback
class RepoBoundaryCallback(private val day:String,
private val service: PHService,
private val cache:PHLocalCache) : PagedList.BoundaryCallback<Post>() {
// keep the last requested page.
// When the request is successful, increment the page number.
private var lastRequestedPage = 1
private val _networkErrors = MutableLiveData<String>()
// LiveData of network errors.
val networkErrors: LiveData<String>
get() = _networkErrors
// avoid triggering multiple requests in the same time
private var isRequestInProgress = false
/**
* This method is called at the very beggining
*/
override fun onZeroItemsLoaded() {
requestAndSaveData()
}
/**
* This method will tell when the user reached the end of the recycler view
*/
override fun onItemAtEndLoaded(itemAtEnd: Post) {
requestAndSaveData()
//TODO resolver este bug
//ele aqui sabe que chegou ao fim , o problema desta API é que nao dá o total de páginas
// e quando ultrapassa as paginas que deve ela dá dados repetidos
// como o onConflit está replace ele está sempre a substituir os items e sempre a actualizar
}
/**
* Requests data from the API and increment the page in case of success
* Save the fetched data into the database to allow offline usage
*/
private fun requestAndSaveData(){
//TODO ao atingir o total de páginas o isRequestInProgress estará a null(o problema de estar sempre a actualizar vem daqui)
if (isRequestInProgress) return
isRequestInProgress = true
getPosts(service,day,lastRequestedPage,BuildConfig.API_KEY, NETWORK_PAGE_SIZE,{ repos ->
cache.insert(repos){
lastRequestedPage++
isRequestInProgress = false
}
},{error ->
_networkErrors
isRequestInProgress = false
})
}
/**
* static block to have the page size to the network calls
*/
companion object {
private const val NETWORK_PAGE_SIZE = 10
}
}
This is my PostDao because I think that order the items should fix it
@Dao
interface PostDao {
@Query("SELECT * FROM product_post ORDER BY votesCount DESC, productName ASC")
fun loadPosts() : DataSource.Factory<Int,Post>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAll(message: List<Post>)
}
This is my repository
class PHRepository (private val service:PHService,
private val cache: PHLocalCache) {
/**
* Search repositories whose names match the query.
*/
fun search(day: String): PostResult {
// Get data source factory from the local cache
val dataSourceFactory = cache.loadPosts(day)
// Construct the boundary callback
val boundaryCallback = RepoBoundaryCallback(day, service,cache)
val networkErrors = boundaryCallback.networkErrors
// Get the paged list
val data = LivePagedListBuilder(dataSourceFactory, DATABASE_PAGE_SIZE)
.setBoundaryCallback(boundaryCallback)
.build()
// Get the network errors exposed by the boundary callback
return PostResult(data)
}
companion object {
private const val DATABASE_PAGE_SIZE = 20
}
}
This is my ViewModel
class PostsViewModel @Inject constructor(private val phRepository: PHRepository) : ViewModel() {
companion object {
private const val VISIBLE_THRESHOLD = 5
}
private val queryLiveData = MutableLiveData<String>()
private val repoResult: LiveData<PostResult> = Transformations.map(queryLiveData, {
phRepository.search(it)
})
val repos: LiveData<PagedList<Post>> = Transformations.switchMap(repoResult,
{ it -> it.data })
/**
* Search a repository based on a query string.
*/
fun searchRepo(queryString: String) {
queryLiveData.postValue(queryString)
}
/**
* Get the last query value.
*/
fun lastQueryValue(): String? = queryLiveData.value
}
This is my Fragment
class PostFragment : BaseFragment<FragmentPostsBinding, PostsViewModel>() {
companion object {
fun newInstance() = PostFragment()
}
private lateinit var viewModelFrag :PostsViewModel //TODO nao foi inicializado
private val adapter = PostAdapter()
override fun layoutToInflate(): Int = R.layout.fragment_posts
override fun defineViewModel(): PostsViewModel {
// get the view model
viewModelFrag = ViewModelProviders.of(this, Injection.provideViewModelFactory(context))
.get(PostsViewModel::class.java)
return viewModelFrag
}
override fun doOnCreated() {
initAdapter()
retrieveData()
}
private fun initAdapter() {
dataBinding.rclChatContent.adapter = adapter
viewModelFrag.repos.observe(this, Observer<PagedList<Post>> {
Log.d("Activity", "list: ${it?.size}")
adapter.submitList(it)
})
dataBinding.rclChatContent.layoutManager = LinearLayoutManager(context)
dataBinding.rclChatContent.addOnItemTouchListener(OnItemTouchListener(context,dataBinding.rclChatContent,
object : TouchListener {
override fun onTouch(view: View?, position: Int?) {
val item = adapter.retrieveItem(position?:return)
Toast.makeText(context, "Clicou em" + item?.productName , Toast.LENGTH_LONG).show()
}
override fun onLongTouch(view: View?, position: Int?) {
val item = adapter.retrieveItem(position?:return)
Toast.makeText(context, "Clicou longo em" + item?.productName, Toast.LENGTH_LONG).show()
}
}))
}
private fun retrieveData() {
viewModelFrag.searchRepo("2018-07-31")
adapter.submitList(null)
}
}
As someone had this problem our can help me?