Livedata 正在处理一个 activity 但不处理其他 activity
Livedata is working on one activity but not working on other activity
我正在从 SQLite 数据库加载动物信息列表。我使用过 MVVM 架构。我在 MainActivity
中有两个按钮,可以启动两个不同的活动。一个是 AnimalAugmented
另一个是 AnimalIntroducer
。在这两项活动中,我加载了相同的数据。为了在 AnimalAugmented
中加载数据,我使用了以下代码
RecyclerView recyclerView = findViewById(R.id.recycler_view_animals);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
AnimalAdapter animalAdapter = new AnimalAdapter();
recyclerView.setAdapter(animalAdapter);
animalViewModel = ViewModelProviders.of(this).get(AnimalViewModel.class);
animalViewModel.getAllAnimals().observe(this, animals -> {
animalAdapter.setAnimals(animals);
});
它工作正常。但是当我尝试在 AnimalIntroducer
中加载数据时,它没有显示任何项目。对于 AnimalIntroducer
我使用了以前的代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animal_introducer);
RecyclerView recyclerView = findViewById(R.id.recycler_view_animal_introducer);
recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
recyclerView.setHasFixedSize(true);
AnimalAdapter animalAdapter = new AnimalAdapter();
recyclerView.setAdapter(animalAdapter);
animalViewModel = ViewModelProviders.of(this).get(AnimalViewModel.class);
animalViewModel.getAllAnimals().observe(this, animals -> {
animalAdapter.setAnimals(animals);
Log.e(TAG, "onCreate: grid "+animals.size());
for(Animal animal:animals){
Log.e(TAG,animal.getBanglaName());
}
});
}
此处它按预期在日志中打印动物列表的大小,但不显示任何项目。但是,如果我从 ArrayList 而不是 ViewModel 加载数据,它就可以工作。那么,为什么我的 activity 没有显示来自 SQLite 的任何项目?
animalAdapter.setAnimals(AnimalDump.insertToList());
这是我的AnimalAdapter
class
public class AnimalAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = "Augmented";
private static final int TYPE_FREE = 1;
private static final int TYPE_LOCKED = 2;
List<Animal> animals= new ArrayList<>();
public OnItemClickListener listener;
public AnimalAdapter() {
Log.d(TAG, "AnimalAdapter: ");
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view;
if(viewType==TYPE_FREE){
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_animal,parent,false);
return new AnimalViewHolder(view);
}
else {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_animal_locked,parent,false);
return new LockedAnimalViewHolder(view);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
Animal animal=animals.get(position);
if(animal.isOffline()){
((AnimalViewHolder)holder).setValues(animal);
}
else {
((LockedAnimalViewHolder)holder).setValues(animal);
}
}
@Override
public int getItemCount() {
return animals.size();
}
public void setAnimals(List<Animal> animals) {
this.animals = animals;
Log.d(TAG, "setAnimals: ");
}
@Override
public int getItemViewType(int position) {
if(animals.get(position).isOffline())
return TYPE_FREE;
else
return TYPE_LOCKED;
}
public void setListener(OnItemClickListener listener) {
this.listener = listener;
}
protected class AnimalViewHolder extends RecyclerView.ViewHolder {
private ImageView itemAnimalImageView;
private TextView itemAnimalTextView;
private Context context;
public CardView itemCardView;
public AnimalViewHolder(@NonNull View itemView) {
super(itemView);
itemAnimalImageView=itemView.findViewById(R.id.item_animal_image_view);
itemAnimalTextView=itemView.findViewById(R.id.item_animal_text_view);
itemCardView = itemView.findViewById(R.id.item_card_view);
context = itemView.getContext();
itemView.setOnClickListener(view -> {
int position = getAdapterPosition();
if(listener!=null && position!=RecyclerView.NO_POSITION){
listener.onItemClick(animals.get(position));
}
YoYo.with(Techniques.RollIn)
.duration(700)
.repeat(0)
.playOn(itemAnimalImageView);
});
}
public void setValues(Animal animal){
itemAnimalTextView.setText(animal.getBanglaName());
itemAnimalImageView.setImageResource(context.getResources().getIdentifier(animal.getId(),"drawable",context.getPackageName()));
}
}
protected class LockedAnimalViewHolder extends RecyclerView.ViewHolder {
private ImageView itemAnimalImageView,itemLockIcon;
private TextView itemAnimalTextView;
private Context context;
public CardView itemCardView;
public LockedAnimalViewHolder(@NonNull View itemView) {
super(itemView);
itemAnimalImageView=itemView.findViewById(R.id.item_animal_image_view);
itemAnimalTextView=itemView.findViewById(R.id.item_animal_text_view);
itemCardView = itemView.findViewById(R.id.item_card_view);
itemLockIcon = itemView.findViewById(R.id.icon_lock);
context = itemView.getContext();
itemView.setOnClickListener(view -> {
YoYo.with(Techniques.RubberBand)
.duration(700)
.repeat(0)
.playOn(itemAnimalImageView);
});
}
public void setValues(Animal animal){
itemAnimalTextView.setText(animal.getBanglaName());
itemAnimalImageView.setImageResource(context.getResources().getIdentifier(animal.getId(),"drawable",context.getPackageName()));
}
}
public interface OnItemClickListener{
void onItemClick(Animal animal);
}
在 this.animals = animals;
之后在 setAnimals(..)
内调用 notifyDataSetChaged()
您必须在列表数据更改后调用 notifyDataSetChaged()
RecyclerView Adapters 要求您通知他们有关数据集的任何更改。显然,适配器无法神奇地知道您向列表中添加了一个项目。所以至少,您需要调用 notifyDataSetChanged()
,这只会使所有项目无效并再次呈现它们。
在您的情况下,您可能希望将此添加到您的 setAnimals
方法中:
public void setAnimals(List<Animal> animals) {
this.animals = animals;
notifyDataSetChanged(); // << this is important
Log.d(TAG, "setAnimals: ");
}
我正在从 SQLite 数据库加载动物信息列表。我使用过 MVVM 架构。我在 MainActivity
中有两个按钮,可以启动两个不同的活动。一个是 AnimalAugmented
另一个是 AnimalIntroducer
。在这两项活动中,我加载了相同的数据。为了在 AnimalAugmented
中加载数据,我使用了以下代码
RecyclerView recyclerView = findViewById(R.id.recycler_view_animals);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
AnimalAdapter animalAdapter = new AnimalAdapter();
recyclerView.setAdapter(animalAdapter);
animalViewModel = ViewModelProviders.of(this).get(AnimalViewModel.class);
animalViewModel.getAllAnimals().observe(this, animals -> {
animalAdapter.setAnimals(animals);
});
它工作正常。但是当我尝试在 AnimalIntroducer
中加载数据时,它没有显示任何项目。对于 AnimalIntroducer
我使用了以前的代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animal_introducer);
RecyclerView recyclerView = findViewById(R.id.recycler_view_animal_introducer);
recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
recyclerView.setHasFixedSize(true);
AnimalAdapter animalAdapter = new AnimalAdapter();
recyclerView.setAdapter(animalAdapter);
animalViewModel = ViewModelProviders.of(this).get(AnimalViewModel.class);
animalViewModel.getAllAnimals().observe(this, animals -> {
animalAdapter.setAnimals(animals);
Log.e(TAG, "onCreate: grid "+animals.size());
for(Animal animal:animals){
Log.e(TAG,animal.getBanglaName());
}
});
}
此处它按预期在日志中打印动物列表的大小,但不显示任何项目。但是,如果我从 ArrayList 而不是 ViewModel 加载数据,它就可以工作。那么,为什么我的 activity 没有显示来自 SQLite 的任何项目?
animalAdapter.setAnimals(AnimalDump.insertToList());
这是我的AnimalAdapter
class
public class AnimalAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = "Augmented";
private static final int TYPE_FREE = 1;
private static final int TYPE_LOCKED = 2;
List<Animal> animals= new ArrayList<>();
public OnItemClickListener listener;
public AnimalAdapter() {
Log.d(TAG, "AnimalAdapter: ");
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view;
if(viewType==TYPE_FREE){
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_animal,parent,false);
return new AnimalViewHolder(view);
}
else {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_animal_locked,parent,false);
return new LockedAnimalViewHolder(view);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
Animal animal=animals.get(position);
if(animal.isOffline()){
((AnimalViewHolder)holder).setValues(animal);
}
else {
((LockedAnimalViewHolder)holder).setValues(animal);
}
}
@Override
public int getItemCount() {
return animals.size();
}
public void setAnimals(List<Animal> animals) {
this.animals = animals;
Log.d(TAG, "setAnimals: ");
}
@Override
public int getItemViewType(int position) {
if(animals.get(position).isOffline())
return TYPE_FREE;
else
return TYPE_LOCKED;
}
public void setListener(OnItemClickListener listener) {
this.listener = listener;
}
protected class AnimalViewHolder extends RecyclerView.ViewHolder {
private ImageView itemAnimalImageView;
private TextView itemAnimalTextView;
private Context context;
public CardView itemCardView;
public AnimalViewHolder(@NonNull View itemView) {
super(itemView);
itemAnimalImageView=itemView.findViewById(R.id.item_animal_image_view);
itemAnimalTextView=itemView.findViewById(R.id.item_animal_text_view);
itemCardView = itemView.findViewById(R.id.item_card_view);
context = itemView.getContext();
itemView.setOnClickListener(view -> {
int position = getAdapterPosition();
if(listener!=null && position!=RecyclerView.NO_POSITION){
listener.onItemClick(animals.get(position));
}
YoYo.with(Techniques.RollIn)
.duration(700)
.repeat(0)
.playOn(itemAnimalImageView);
});
}
public void setValues(Animal animal){
itemAnimalTextView.setText(animal.getBanglaName());
itemAnimalImageView.setImageResource(context.getResources().getIdentifier(animal.getId(),"drawable",context.getPackageName()));
}
}
protected class LockedAnimalViewHolder extends RecyclerView.ViewHolder {
private ImageView itemAnimalImageView,itemLockIcon;
private TextView itemAnimalTextView;
private Context context;
public CardView itemCardView;
public LockedAnimalViewHolder(@NonNull View itemView) {
super(itemView);
itemAnimalImageView=itemView.findViewById(R.id.item_animal_image_view);
itemAnimalTextView=itemView.findViewById(R.id.item_animal_text_view);
itemCardView = itemView.findViewById(R.id.item_card_view);
itemLockIcon = itemView.findViewById(R.id.icon_lock);
context = itemView.getContext();
itemView.setOnClickListener(view -> {
YoYo.with(Techniques.RubberBand)
.duration(700)
.repeat(0)
.playOn(itemAnimalImageView);
});
}
public void setValues(Animal animal){
itemAnimalTextView.setText(animal.getBanglaName());
itemAnimalImageView.setImageResource(context.getResources().getIdentifier(animal.getId(),"drawable",context.getPackageName()));
}
}
public interface OnItemClickListener{
void onItemClick(Animal animal);
}
在 this.animals = animals;
setAnimals(..)
内调用 notifyDataSetChaged()
您必须在列表数据更改后调用 notifyDataSetChaged()
RecyclerView Adapters 要求您通知他们有关数据集的任何更改。显然,适配器无法神奇地知道您向列表中添加了一个项目。所以至少,您需要调用 notifyDataSetChanged()
,这只会使所有项目无效并再次呈现它们。
在您的情况下,您可能希望将此添加到您的 setAnimals
方法中:
public void setAnimals(List<Animal> animals) {
this.animals = animals;
notifyDataSetChanged(); // << this is important
Log.d(TAG, "setAnimals: ");
}