gpt4 book ai didi

android - 使用 Google 的分页库更新 PagedList 中的单个项目

转载 作者:行者123 更新时间:2023-12-03 20:57:23 29 4
gpt4 key购买 nike

我在 RecyclerView 中有一个简单的口袋妖怪列表,只有口袋妖怪的名字和一个“最喜欢的”切换按钮。我正在使用带有 PageKeyedDataSource 的 Android JetPack 的分页库来检索小块 Pokemon 并将它们显示给用户。只要 Activity 没有被破坏,我只希望数据保持不变(即,我不想将数据保持到 Room 或数据库,而是只要 ViewModel 还活着就让它保持不变)。

Screenshot of app

我希望能够单击任何 Pokemon 项目上的心形按钮并将 SimplePokemon 模型中的“isFavorite”字段更新为 truefalse .据我了解,如果我想更改该 PagedList 中的单个项目,我需要使 DataSource 无效,并且理论上应该生成一个 PagedList 的新 LiveData,可以将其提供给 Adapter 并显示在屏幕上。

问题:如何在不需要 Room 或其他数据库的情况下使用分页库更新 PagedList 中的单个项目?

将来,我想将此解决方案扩展到用户可以喜欢帖子的社交媒体提要,但我不知道是否有必要(或有效)将社交提要项目存储在诸如 Room 之类的数据库中,因为这些提要项目不断变化。所以我选择将它们存储在 ViewModel 中,然后在每次用户退出应用程序时清除它们。

到目前为止,这是我的代码:

SimplePokemon.kt:

data class SimplePokemon(
@SerializedName("name") val name: String,
@SerializedName("url") val url: String,
var isFavorite: Boolean = false
)

PokemonViewModel.kt:
class PokemonViewModel(application: Application) : AndroidViewModel(application) {

private val config = PagedList.Config.Builder()
.setPageSize(20)
.setEnablePlaceholders(false)
.build()

private fun initializedPagedListBuilder(config: PagedList.Config): LivePagedListBuilder<String, SimplePokemon> {
val dataSourceFactory = object : DataSource.Factory<String, SimplePokemon>() {
override fun create(): DataSource<String, SimplePokemon> {
return PokemonDataSource()
}
}
return LivePagedListBuilder<String, SimplePokemon>(dataSourceFactory, config)
}

fun pokemonPagedListLiveData(): LiveData<PagedList<SimplePokemon>> {
return initializedPagedListBuilder(config).build()
}
}

PokemonAdapter.kt:
class PokemonAdapter :
PagedListAdapter<SimplePokemon, PokemonAdapter.PokemonViewHolder>(PokemonDiffUtil()) {

inner class PokemonViewHolder(v: View) : RecyclerView.ViewHolder(v) {
private val pokemonNameTextView: TextView = v.findViewById(R.id.pokemon_name_text_view)
private val pokemonFavoriteToggle: ToggleButton =
v.findViewById(R.id.pokemon_favorite_toggle_button)

fun bind(data: SimplePokemon) {
pokemonNameTextView.text = data.name
pokemonFavoriteToggle.isChecked = data.isFavorite
}
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PokemonViewHolder {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.item_simple_pokemon, parent, false)
return PokemonViewHolder(view)
}

override fun onBindViewHolder(holder: PokemonViewHolder, position: Int) {
val item = getItem(position)
item?.let { holder.bind(it) }
}
}

PokemonDataSource.kt:
class PokemonDataSource : PageKeyedDataSource<String, SimplePokemon>() {

private val api = NetworkService.pokemonNetworkInterface

override fun loadInitial(
params: LoadInitialParams<String>,
callback: LoadInitialCallback<String, SimplePokemon>
) {
api.getPokemon().enqueue(object : Callback<PokeResponse<List<SimplePokemon>>> {

override fun onFailure(call: Call<PokeResponse<List<SimplePokemon>>>?, t: Throwable?) {
Log.e("PokemonDataSource", "Failed to fetch data!")
}

override fun onResponse(
call: Call<PokeResponse<List<SimplePokemon>>>?,
response: Response<PokeResponse<List<SimplePokemon>>>
) {
val listing = response.body()
val pokemon = listing?.results
callback.onResult(pokemon ?: listOf(), listing?.previous, listing?.next)
}
})
}

override fun loadAfter(
params: LoadParams<String>,
callback: LoadCallback<String, SimplePokemon>
) {
api.getPokemon(url = params.key)
.enqueue(object : Callback<PokeResponse<List<SimplePokemon>>> {
override fun onFailure(
call: Call<PokeResponse<List<SimplePokemon>>>?,
t: Throwable?
) {
Log.e("PokemonDataSource", "Failed to fetch data! Oh Noooo!")
}

override fun onResponse(
call: Call<PokeResponse<List<SimplePokemon>>>?,
response: Response<PokeResponse<List<SimplePokemon>>>
) {
val listing = response.body()
val pokemon = listing?.results
callback.onResult(pokemon ?: listOf(), listing?.next)
}
})
}

override fun loadBefore(
params: LoadParams<String>,
callback: LoadCallback<String, SimplePokemon>
) {
api.getPokemon(url = params.key)
.enqueue(object : Callback<PokeResponse<List<SimplePokemon>>> {
override fun onFailure(
call: Call<PokeResponse<List<SimplePokemon>>>?,
t: Throwable?
) {
Log.e("PokemonDataSource", "Failed to fetch data! Oh Noooo!")
}

override fun onResponse(
call: Call<PokeResponse<List<SimplePokemon>>>?,
response: Response<PokeResponse<List<SimplePokemon>>>
) {
val listing = response.body()
val pokemon = listing?.results
callback.onResult(pokemon ?: listOf(), listing?.previous)
}
})
}


我还想确保每次更新 DataSource 时 RecyclerView 都不会跳到顶部。

理想的情况是,只要 Activity 处于 Activity 状态并能够在本地更新单个 Pokemon 项目,就保留一个 Pokemon 列表。从理论上讲,我还会向后端发送一个 POST 请求以更新后端的口袋妖怪,但我只是想让问题保持简单。

任何帮助将不胜感激。

最佳答案

为了更新 PagedListAdapter 中的单个项目,我在 PagedListAdapter 中添加了这个方法。
就我而言。

    // Adapter Class
public class ChatHistoryAdapter extends PagedListAdapter<ChatHistoryEntity, ChatHistoryAdapter.ViewHolder> {

OnClickListener<ChatHistoryEntity> listener;
Context mContext;


public ChatHistoryAdapter(Context context) {
super(DIFF_CALLBACK);
mContext = context;
}

public void setOnClickListener(OnClickListener<ChatHistoryEntity> listener) {
this.listener = listener;
}


@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
ItemChatHistoryBinding binding =
ItemChatHistoryBinding.inflate(layoutInflater,parent,false);

return new ViewHolder(binding);
}

@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
ChatHistoryEntity current = getChat(position);
holder.binding.tvSender.setText(current.getName_or_mobile_or_groupName());
holder.binding.tvMessage.setText(current.getSubject());
// holder.binding.tvTimestamp.setText(current.getMessage_date_time().toString());

// holder.tv_sender.setText(current.getContact_name_or_mobile_or_groupName());
// holder.tv_message.setText(current.getMessage());

if (current.isSelected()){
holder.binding.mainLayout.setBackgroundColor(ContextCompat.getColor(mContext, R.color.item_selection));
// holder.binding.mainLayout.setBackgroundColor();
}else {
holder.binding.mainLayout.setBackgroundColor(0);
}


holder.Bind(current,listener,position);

}

public ChatHistoryEntity getChat(int position) {
return getItem(position);
}

public void updateItemSelection(int position,boolean isSelect){
ChatHistoryEntity current = getChat(position);
current.setSelected(isSelect);
notifyDataSetChanged();
}

public void clearSelection(){
List<ChatHistoryEntity> collect = StreamSupport.stream(getCurrentList().snapshot())
.peek(o -> o.setSelected(false))
.collect(Collectors.toList());

// submitList(PagedList<ChatHistoryEntity> list = new PagedList<>());
notifyDataSetChanged();
}


private static final DiffUtil.ItemCallback<ChatHistoryEntity> DIFF_CALLBACK =
new DiffUtil.ItemCallback<ChatHistoryEntity>() {
@Override
public boolean areItemsTheSame(@NonNull ChatHistoryEntity oldItem,
@NonNull ChatHistoryEntity newItem) {
return oldItem.getId() == newItem.getId();
}

@Override
public boolean areContentsTheSame(@NonNull ChatHistoryEntity oldItem,
@NonNull ChatHistoryEntity newItem) {
return oldItem.getId() == newItem.getId()
&& oldItem.getName_or_mobile_or_groupName()
.equalsIgnoreCase(newItem.getName_or_mobile_or_groupName());
}
};

public static class ViewHolder extends RecyclerView.ViewHolder {

ItemChatHistoryBinding binding;

public ViewHolder(ItemChatHistoryBinding binding) {
super(binding.getRoot());
this.binding =binding;

}


void Bind(ChatHistoryEntity chatEntity, OnClickListener<ChatHistoryEntity> mOnCharacterClick,
int position) {

binding.mainLayout.setOnClickListener(v ->
mOnCharacterClick.OnClick(chatEntity,"",position));
}
}

}

// Activity or fragument Class.
public class MainActivity extends AppCompatActivity {

mAdapter.setOnClickListener((currentObj, mode, position) -> {
// This is how you update single item in PagedListAdapter list.
mAdapter.updateItemSelection(position,!currentObj.isSelected())
});


}

关于android - 使用 Google 的分页库更新 PagedList 中的单个项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60271737/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com