簡體   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