我正在使用Android Paging Library,但无法从DataSource获取结果。

我基本上是从LivePagedListBuilder获取一个空的LiveData。不知道我在做什么错。我的loadInitial也从未调用过。

这是我的ViewModel:

class WorkPackagesViewModel: ViewModel() {

  companion object {
    const val PAGING_LIMIT_DEFAULT = 10
  }
  var workPackages: LiveData<PagedList<WorkPackagesQuery.WorkPackage>>? = null

  fun fetchWorkPackages(isOnline: Boolean, workWeeK: Configurations.AppWeek, pagingStart: Int?, pagingLimit: Int?) {

        val myConfig = PagedList.Config.Builder()
                .setInitialLoadSizeHint(pagingLimit ?: PAGING_LIMIT_DEFAULT)
                .setPageSize(pagingLimit ?: PAGING_LIMIT_DEFAULT )
                .build()

        val workPackageDataFactory = WorkPackageDataFactory(workWeeK)
        workPackageDataFactory.create()

        workPackages = LivePagedListBuilder(workPackageDataFactory, myConfig)
                .setInitialLoadKey(pagingStart)
                .setFetchExecutor(Executors.newFixedThreadPool(5))
                .build()
    }
  }

}


这是我的DataSource.Factory:

class WorkPackageDataFactory(
  private val workWeek : Configurations.AppWeek
)  : DataSource.Factory<Int, WorkPackagesQuery.WorkPackage>() {

private var mutableLiveData: MutableLiveData<WorkPackageDataSource>? = MutableLiveData()

  override fun create(): DataSource<Int, WorkPackagesQuery.WorkPackage> {

      val workPackageDataSource = WorkPackageDataSource(workWeek)
      mutableLiveData?.postValue(workPackageDataSource)
      return workPackageDataSource

  }

}


这是我的数据源文件:

class WorkPackageDataSource(
   private val workWeek : Configurations.AppWeek
) : PageKeyedDataSource<Int, WorkPackagesQuery.WorkPackage>(), KoinComponent
{

  val client :  PipefighterApi by inject()
  private var parentJob = Job()
  private val coroutineContext: CoroutineContext get() = parentJob + Dispatchers.Main
  private val scope = CoroutineScope(coroutineContext)

  override fun loadInitial( //DOES NOT GET CALLED
    params: LoadInitialParams<Int>,
    callback: LoadInitialCallback<Int, WorkPackagesQuery.WorkPackage>
  ) {
    scope.launch {
        val workPackages = getWorkPackages(1,params.requestedLoadSize)?.workPackages() as MutableList<WorkPackagesQuery.WorkPackage>

        callback.onResult(workPackages, null, params.requestedLoadSize + 1 )
    }


  }

  override fun loadAfter(
    params: LoadParams<Int>,
    callback: LoadCallback<Int, WorkPackagesQuery.WorkPackage>
    ) {
    scope.launch {
        val workPackages = getWorkPackages(params.key,params.requestedLoadSize)?.workPackages() as MutableList<WorkPackagesQuery.WorkPackage>
        var nextKey : Int? = null
        if  (params.key.plus(0) != workPackages.size) {
            nextKey = params.key.plus(1)
        }
        callback.onResult(workPackages, nextKey )
    }

  }

  override fun loadBefore(
    params: LoadParams<Int>,
    callback: LoadCallback<Int, WorkPackagesQuery.WorkPackage>
   ) {

  }

  suspend fun getWorkPackages(
    initialPage : Int,
    requestedLoadSize : Int
  ) : WorkPackagesQuery.Result? {
    return withContext(Dispatchers.IO) {
        async {  client.workPackages(
            workWeek.currentWeekStart(),
            workWeek.currentWeekEnd(),
            initialPage,
            requestedLoadSize
            ) }.await().response
    }
  }

}


这是我的片段

class WorkPackagesFragment : Fragment(), WorkPackagesRecyclerAdapter.OnClickWorkPackage {

  companion object {
    private const val VERTICAL_ITEM_SPACE = 30
    const val PAGING_START = 1
    const val PAGING_LIMIT = 10
  }

  private val workPackagesViewModel: WorkPackagesViewModel by viewModel()
  private val mainViewModel : MainViewModel by sharedViewModel()
  private val networkConnection: NetworkConnectionHelper by inject()
  private lateinit var binding: FragmentWorkPackagesBinding
  private lateinit var adapter: WorkPackagesRecyclerAdapter

  override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
  ): View? {
    binding = DataBindingUtil.inflate(
        inflater,
        com.bechtel.pf.R.layout.fragment_work_packages,
        container,
        false
    )

    mainViewModel.week.observe(this, Observer {
        it ?: return@Observer

        workPackagesViewModel.fetchWorkPackages(networkConnection.connected(), it, PAGING_START, PAGING_LIMIT)
    })


    binding.lifecycleOwner = viewLifecycleOwner
    binding.viewModel = workPackagesViewModel

    workPackagesViewModel.workPackages?.observe(this, Observer {
        it ?: return@Observer

        adapter = WorkPackagesRecyclerAdapter(this)
        adapter.submitList(it)
        binding.workPackagesRecyclerView.adapter = adapter
        adapter.notifyDataSetChanged()
    })

    return binding.root
  }

}

最佳答案

我看不到在哪里观察到workPackages,但是我想问题是您在调用workPackages之前观察到了fetchWorkPackages()。调用fetchWorkPackages()时,它将创建一个新的LiveData并将新的LiveData分配给workPackages。但是您之前只观察了workPackages中的旧LiveData,因此该新监视者没有任何活动的观察者,因此它永远不会触发loadInitial()

您可以尝试在ViewModel的fetchWorkPackages()中放入init {},或在Activity或Fragment中调用observe之后将workPackages设置为fetchWorkPackages()

07-26 06:03