繁体   English   中英

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

[英]Viewmodel shows empty recyclerview when activity rotated

我对Android体系结构组件还很陌生,并且一直在尝试从服务器存储数据的空间。 问题是没有数据立即显示在回收者视图中。 在我的recyclerview的正上方有一个searchview(此处未实现任何逻辑),当我单击searchview进行输入时,recyclerview会显示所有本应显示的数据。

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));
    }
}}

主要活动:

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:

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) {
            }
        });
    }
});
}}

如果您不使用DiffUtil及其diffResult.dispatchUpdatesTo(this); 您应该执行notifyDataSetChanged()。 在您的情况下,在RestaurantsAdapter.setData中添加一行:

// first initialization
data = newData;
notifyDataSetChanged();

您的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;
    }
}

newDatanull时,更改适配器的数据源,但不要调用notifyDataSetChanged

这样,您在屏幕上看到的数据将不会更新。


因此,为了解决它:

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();
    }
}

另一件事,如果不是很好的做法,则设置适配器数据集为null。 所以我的建议是将您的数据设置为空列表,而不是null:

data = new ArrayList<>();

问题:您使用的ViewModels错误。 您仅从ViewModel返回数据, 而从未在ViewModel中保存数据

首先在这里阅读ViewModels的工作方式: https//developer.android.com/topic/libraries/architecture/viewmodel

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM