RecyclerView is not refreshing

我们两清 提交于 2020-01-05 04:07:08

问题


In my application I receive some data from a web server. This data is sent to a RecyclerView. Firstly, all data is displayed fine. However, when I try to refresh it, the data no-longer shows. The data arrives from the web service (as verified using Logcat).

Setting the data

ArrayList<FoodItem> allFood = response.body();
if(foodAdapter != null) {
    foodAdapter.swap(allFood);
} else {
    foodAdapter = new FoodAdapter(FoodViewForCustomerActivity.this, allFood);
}
photoCollectionView.setAdapter(foodAdapter);

My RecyclerView Adapter

public class FoodAdapter extends RecyclerView.Adapter<FoodAdapter.ViewHolder> {
    Context mContext;
    ArrayList<FoodItem> foodItems;

    public FoodAdapter(Context context, ArrayList<FoodItem> foodItems) {
        this.mContext = context;
        this.foodItems = foodItems;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.food_item_row, parent, false);
        return new ViewHolder(view);
    }

    public void swap(ArrayList<FoodItem> newFoods) {
        foodItems.clear();
        foodItems.addAll(newFoods);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                notifyDataSetChanged();
            }
        }, 500);
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, final int position) {
        FoodItem foodItem = foodItems.get(position);
        String stringPicture = foodItem.getPhoto();
        byte[] decodedPictureStringArray = Base64.decode(stringPicture, Base64.DEFAULT);
        Bitmap bitmapPhoto = BitmapFactory.decodeByteArray(decodedPictureStringArray, 0, decodedPictureStringArray.length);
        Uri photoUri = getImageUri(mContext, bitmapPhoto);
        Picasso.with(mContext).load(photoUri).resize(300, 300)
            .centerCrop().into(holder.foodImage);
        holder.foodItemNameText.setText(foodItem.getFoodItemName());
        holder.foodPriceText.setText(foodItem.getUnitPrice() + " / " + foodItem.getUnitType());
    }
    public Uri getImageUri(Context inContext, Bitmap inImage) {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        inImage.compress(Bitmap.CompressFormat.JPEG, 10, bytes);
        String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
        return Uri.parse(path);
    }

    @Override
    public int getItemCount() {
        return foodItems.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        public ImageView foodImage;
        public TextView foodItemNameText;
        public TextView foodPriceText;

        public ViewHolder(View itemView) {
            super(itemView);
            foodImage = (ImageView) itemView.findViewById(R.id.foodPhoto);
            foodItemNameText = (TextView) itemView.findViewById(R.id.foodItemNameText);
            foodPriceText = (TextView) itemView.findViewById(R.id.foodPriceText);
        }
    }
}

The RelativeLayout that contains my Toolbar and RecyclerView

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical"
  tools:context=".FoodViewForCustomerActivity">

  <include
      android:id="@+id/toolbar"
      layout="@layout/toolbar"
      />
  <android.support.v7.widget.RecyclerView
      android:layout_below="@id/toolbar"
      android:id="@+id/photoCollectionView"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:background="#f8f8f8"
      android:divider="@null"
      android:listSelector="@android:color/transparent"/>
</RelativeLayout>

回答1:


Sorry, for answering my own question. I solved my question by following solution provided here.Main cause of my problem was that RecyclerView was not calling onCreateViewHolder or onBindView, when i was trying to refresh it.




回答2:


foodAdapter=new FoodAdapter(FoodViewForCustomerActivity.this,allFood);

Change above line. Send foodItems arraylist reference in adapter constructor instead of allFood

Correct line is

foodAdapter=new FoodAdapter(FoodViewForCustomerActivity.this,foodItems);



回答3:


Diagnosis #1

Judging from the comment discussion. It seems like your RecyclerView is being fed the correct data from your source.

However, when the data count is 1, it is hidden underneath other UI elements.

You need to make sure that your RecyclerView is not obscured by other UI elements, such as the Toolbar.

There are multiple ways you can do this.

  • You could add a marginTop of ?attr/actionBarSize to your RecyclerView.
  • You could add a layout rule to ConstraintLayout similar to android:layout_constraintTop_toBottomOf ="@id/toolbar".
  • You could add a layout rule to RelativeLayout similar to android:layout_below="@id/toolbar".

Diagnosis #2

Your code for refreshing data is a little strange:

ArrayList<FoodItem> allFood = response.body();
if(foodAdapter != null) {
    foodAdapter.swap(allFood);
} else {
    foodAdapter = new FoodAdapter(FoodViewForCustomerActivity.this, allFood);
}
photoCollectionView.setAdapter(foodAdapter);

Normally, you do not set the Adapter every time your data has changed. You set it once on initialization, and then refresh the data with the notify methods.

Instead of what you have, please separate the structure as follows:

Member variable of your FoodViewForCustomerActivity:

private ArrayList<FoodItem> mAllFood = new ArrayList<>();

In onCreate():

foodAdapter = new FoodAdapter(FoodViewForCustomerActivity.this, mAllFood);
photoCollectionView.setAdapter(foodAdapter);

In your data collection method:

ArrayList<FoodItem> food = response.body();
if(foodAdapter != null) {
    Log.e(TAG, "Data retrieved (size="+food.size()+"), sending it to Adapter.");
    foodAdapter.swap(food);
} else {
    Log.e(TAG, "Data retrieved (size="+food.size()+"), but Adapter is null!");
}



回答4:


Change code like this

public void swap(ArrayList<FoodItem> newFoods){
    foodItems.clear();
    foodItems.addAll(newFoods);
    foodAdapter.notifyDataSetChanged();
}



回答5:


Fine, you can change too

allFood.clear();
allFood.addAll(newFoods);
notifyDataSetChanged();


来源:https://stackoverflow.com/questions/40605985/recyclerview-is-not-refreshing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!