[英]Viewmodel shows empty recyclerview when activity rotated
I am pretty new to the Android architecture components and have been trying out room for data storage from my server. 我对Android体系结构组件还很陌生,并且一直在尝试从服务器存储数据的空间。 Problem is no data is being shown on the recycler view IMMEDIATELY.
问题是没有数据立即显示在回收者视图中。 There's a searchview(no logic implemented just there) right above my recyclerview and when I click searchview for input, the recyclerview shows all the data which was supposed to be shown earlier.
在我的recyclerview的正上方有一个searchview(此处未实现任何逻辑),当我单击searchview进行输入时,recyclerview会显示所有本应显示的数据。
RestaurantsAdapter: RestaurantsAdapter:
public class RestaurantsAdapter extends RecyclerView.Adapter<RestaurantsAdapter.MyViewHolder> {
private List<Restaurant> data;
private Context context;
private LayoutInflater layoutInflater;
private final Random r = new Random();
public RestaurantsAdapter(Context context) {
this.data = new ArrayList<>();
this.context = context;
this.layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public RestaurantsAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_restaurant, parent, false);
return new RestaurantsAdapter.MyViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull RestaurantsAdapter.MyViewHolder holder, int position) {
holder.rName.setText(data.get(position).getName());
}
public void setData(List<Restaurant> newData) {
if (data != null) {
RestaurantDiffCallback restaurantDiffCallback = new RestaurantDiffCallback(data, newData);
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(restaurantDiffCallback);
data.clear();
data.addAll(newData);
diffResult.dispatchUpdatesTo(this);
} else {
// first initialization
data = newData;
}
}
@Override
public int getItemCount() {
return data.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView rName;
public MyViewHolder(View itemView) {
super(itemView);
rName = (TextView) itemView.findViewById(R.id.restaurant_name);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View view) {
}
}
class RestaurantDiffCallback extends DiffUtil.Callback {
private final List<Restaurant> oldRestaurants, newRestaurants;
public RestaurantDiffCallback(List<Restaurant> oldPosts, List<Restaurant> newPosts) {
this.oldRestaurants = oldPosts;
this.newRestaurants = newPosts;
}
@Override
public int getOldListSize() {
return oldRestaurants.size();
}
@Override
public int getNewListSize() {
return newRestaurants.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldRestaurants.get(oldItemPosition).getIdentifier().equals(newRestaurants.get(newItemPosition).getIdentifier());
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldRestaurants.get(oldItemPosition).equals(newRestaurants.get(newItemPosition));
}
}}
MainActivity: 主要活动:
public class MainActivity extends AppCompatActivity {
private RestaurantsAdapter restaurantsAdapter;
private RestaurantViewModel restaurantViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
restaurantsAdapter = new RestaurantsAdapter(this);
restaurantViewModel = ViewModelProviders.of(this).get(RestaurantViewModel.class);
restaurantViewModel.getAllRestaurants().observe(this, restaurants -> restaurantsAdapter.setData(restaurants));
RecyclerView recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(restaurantsAdapter);
}}
ViewModel: ViewModel:
public class RestaurantViewModel extends AndroidViewModel {
private RestaurantDao restaurantDao;
private ExecutorService executorService;
private ApiInterface webService;
public RestaurantViewModel(@NonNull Application application) {
super(application);
restaurantDao = RestaurantsDatabase.getInstance(application).restaurantDao();
executorService = Executors.newSingleThreadExecutor();
webService = ApiClient.getApiClient().create(ApiInterface.class);
}
LiveData<List<Restaurant>> getAllRestaurants() {
refreshUser();
return restaurantDao.findAll();
}
private void refreshUser() {
executorService.execute(() -> {
int numOfRestaurants = restaurantDao.totalRestaurants();
if (numOfRestaurants < 30) {
Call<RestaurantsModel> call = webService.getRestaurants();
call.enqueue(new Callback<RestaurantsModel>() {
@Override
public void onResponse(@NonNull Call<RestaurantsModel> call, @NonNull Response<RestaurantsModel> response) {
restaurantDao.saveAll(response.body().getData().getData());
}
@Override
public void onFailure(@NonNull Call<RestaurantsModel> call, @NonNull Throwable t) {
}
});
}
});
}}
If you don't use the DiffUtil with its diffResult.dispatchUpdatesTo(this); 如果您不使用DiffUtil及其diffResult.dispatchUpdatesTo(this); you should do notifyDataSetChanged().
您应该执行notifyDataSetChanged()。 In your case, in RestaurantsAdapter.setData add one line:
在您的情况下,在RestaurantsAdapter.setData中添加一行:
// first initialization
data = newData;
notifyDataSetChanged();
You have an issue in your setData
method: 您的
setData
方法中存在问题:
public void setData(List<Restaurant> newData) {
if (data != null) {
RestaurantDiffCallback restaurantDiffCallback = new RestaurantDiffCallback(data, newData);
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(restaurantDiffCallback);
data.clear();
data.addAll(newData);
diffResult.dispatchUpdatesTo(this);
} else {
// first initialization
data = newData;
}
}
When your newData
is null your change the data source of your adapter, but you don't call notifyDataSetChanged
. 当
newData
为null时,更改适配器的数据源,但不要调用notifyDataSetChanged
。
This way the data that you are seeing on the screen will not be updated. 这样,您在屏幕上看到的数据将不会更新。
So in order to fix it: 因此,为了解决它:
public void setData(List<Restaurant> newData) {
if (data != null) {
RestaurantDiffCallback restaurantDiffCallback = new RestaurantDiffCallback(data, newData);
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(restaurantDiffCallback);
data.clear();
data.addAll(newData);
diffResult.dispatchUpdatesTo(this);
} else {
// first initialization
data = newData;
notifyDataSetChanged();
}
}
Another thing, if not a very good practice setting your adapter dataset has null. 另一件事,如果不是很好的做法,则设置适配器数据集为null。 So my suggestion is to set your data as an empty list instead of null:
所以我的建议是将您的数据设置为空列表,而不是null:
data = new ArrayList<>();
The issue: you're using ViewModels incorrectly. 问题:您使用的ViewModels错误。 You are only returning data from the ViewModel, but never saving data in the ViewModel
您仅从ViewModel返回数据, 而从未在ViewModel中保存数据
Start by reading how ViewModels work here: https://developer.android.com/topic/libraries/architecture/viewmodel 首先在这里阅读ViewModels的工作方式: https : //developer.android.com/topic/libraries/architecture/viewmodel
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.