プロジェクトで Android Paging ライブラリを構成して、ページ分割されたメッセージのリストを RecyclerView にロードしようとしています。私の API はオフセットと最大値を使用するため、PositionalDataSource を使用しています。
ここに、DataStore が RetroFit を使用してメッセージをロードする DataSource 実装を示します。メッセージが適切にロードされ、MessageListItem のインスタンスに変換されていることをコンソールで確認できます。
class MessageDataSource: PositionalDataSource<MessageListItem>() {
override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<MessageListItem>) {
DataStore.shared.loadMessages(params.startPosition, params.loadSize) { result, error ->
if(result != null) {
callback.onResult(result.items)
} else {
callback.onError(MessageDataSourceException(error))
}
}
}
override fun loadInitial(
params: LoadInitialParams,
callback: LoadInitialCallback<MessageListItem>
) {
DataStore.shared.loadMessages(params.requestedStartPosition, params.requestedLoadSize) { response, error ->
if(response != null) {
callback.onResult(response.items, response.offset, response.total)
} else {
callback.onError(MessageDataSourceException(error))
}
}
}
}
class MessageDataSourceException(rootCause: Throwable? = null): Exception(rootCause)
ここに私の DataSourceFactory 実装があります:
class MessageDataSourceFactory: DataSource.Factory<Int, MessageListItem>() {
val messageLiveDataSource = MutableLiveData<MessageDataSource>()
private lateinit var messageDataSource: MessageDataSource
override fun create(): DataSource<Int, MessageListItem> {
messageDataSource = MessageDataSource()
messageLiveDataSource.postValue(messageDataSource)
return messageDataSource
}
}
これが私の MessageListAdapter 実装です:
object MessageListItemDiff: DiffUtil.ItemCallback<MessageListItem>() {
override fun areItemsTheSame(oldItem: MessageListItem, newItem: MessageListItem): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: MessageListItem, newItem: MessageListItem): Boolean {
return oldItem == newItem
}
}
class MessageListAdapter(private val clickListener: View.OnClickListener):
PagedListAdapter<MessageListItem, MessageListAdapter.MessageHolder>(MessageListItemDiff) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageHolder {
val inflatedView = LayoutInflater.from(parent.context).inflate(R.layout.item_message, parent, false)
return MessageHolder(inflatedView, clickListener)
}
override fun onBindViewHolder(holder: MessageHolder, position: Int) {
holder.bind(getItem(position)!!)
}
class MessageHolder(itemView: View, private val clickListener: View.OnClickListener) : RecyclerView.ViewHolder(itemView) {
val unreadIndicator = itemView.findViewById<ImageView>(R.id.unreadIndicator)
val title = itemView.findViewById<TextView>(R.id.title)
val dateSent = itemView.findViewById<TextView>(R.id.dateSent)
val cardView = itemView.findViewById<CardView>(R.id.card_view)
fun bind(message: MessageListItem) {
cardView.tag = message
cardView.setOnClickListener(clickListener)
title.text = message.title
dateSent.text = TimeAgo.using(message.dateSent.time)
if(message.isRead) {
unreadIndicator.setImageResource(0)
} else {
unreadIndicator.setImageResource(R.drawable.ic_unread)
}
}
}
}
そして最後に私のViewModel:
class MessageListViewModel: ViewModel() {
val messagePagedList: LiveData<PagedList<MessageListItem>>
val liveDataSource: LiveData<MessageDataSource>
init {
val messageDataSourceFactory = MessageDataSourceFactory()
liveDataSource = messageDataSourceFactory.messageLiveDataSource
val pagedListConfig = PagedList.Config.Builder()
.setEnablePlaceholders(false)
.setPageSize(30)
.setPrefetchDistance(90)
.build()
messagePagedList = LivePagedListBuilder(messageDataSourceFactory, pagedListConfig).build()
}
}
次に示すのは、messageList と呼ばれるリサイクラー ビューを表示することになっているフラグメントの onViewCreated 実装です。
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
messageList.layoutManager = LinearLayoutManager(context!!)
messageList.setHasFixedSize(true)
messageListViewModel = ViewModelProvider(this).get(MessageListViewModel::class.java)
messageListAdapter = MessageListAdapter(this)
messageListViewModel.messagePagedList.observe(this, Observer { messages ->
messageListAdapter.submitList(messages)
})
messageList.adapter = messageListAdapter
}
問題は、データがサーバーからロードされていることを確認できますが、リサイクラー ビューに到達しないことです。オブザーバー行 ( messageListAdapter.submitList(messages)
) にブレークポイントを追加すると、空のメッセージ リストで 1 回呼び出しが行われ、それだけです。
私はこれらすべてのクラスとそれらが何をすべきかについて本当に混乱していることを認めなければなりません. Room データベース、RxJava、または PageKeyedDataSource。ほとんどのサンプルが行っています。
何が起こっているのでしょうか?