简体   繁体   English

活动旋转时,ViewModel显示空的RecyclerView

[英]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 . newDatanull时,更改适配器的数据源,但不要调用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.

相关问题 ViewModel Observer 显示空的 RecyclerView - ViewModel Observer shows empty RecyclerView 无法移交列表<obj> (来自单<list<obj> &gt;) 从 ViewModel 到 Activity。 RecyclerView 保持为空。 原因在哪里? </list<obj></obj> - Cannot handover List<Obj> (got from Single<List<Obj>>) from ViewModel to Activity. RecyclerView stays empty. Where is the cause? 显示时RecyclerView为空 - RecyclerView is empty when display 如果ArrayList为空,为什么不显示RecyclerView没有标题? - Why shows the RecyclerView no header if the ArrayList is empty? 旋转屏幕时如何重新创建Android Activity? - How is an Android Activity recreated when the screen is rotated? 当列表不为空时,ListFragment显示空文本 - ListFragment shows empty text when the list is not empty RecyclerView在触发activity onStop时释放MediaPlayer - RecyclerView release MediaPlayer when activity onStop is triggered Android活动已轮换 - Android Activity Rotated Room + ViewModel + LiveData + RecyclerView (MVVM) 第 7 部分 - 添加注意活动 - Android 教程崩溃 - Room + ViewModel + LiveData + RecyclerView (MVVM) Part 7 - ADD NOTE ACTIVITY - Android Tutorial crashes RecyclerView with ViewModel in Fragment in Java - RecyclerView with ViewModel in Fragment in Java
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM