RecyclerView не показывает списки, но данные передаются в адаптер - PullRequest
2 голосов
/ 16 июня 2020

Я получаю данные из FireStore в объект настраиваемого класса, когда я использую Toast в течение l oop, я могу отображать все данные, которые я хочу, но список, который я передаю своему адаптер пуст.

Я пытался точно определить, почему он пуст, но ничего не работало.

Вот мой основной класс:

products.whereEqualTo("IDliv","kITQ8wiPshsnWqHDlP5D").addSnapshotListener(new EventListener<QuerySnapshot>() {
        @Override
        public void onEvent(@Nullable QuerySnapshot documentSnapshots, @Nullable FirebaseFirestoreException e) {
            assert documentSnapshots != null;
            for (DocumentChange document : documentSnapshots.getDocumentChanges()) {
            generalObject obj=document.getDocument().toObject(generalObject.class);
            for(int i=0;i<obj.getproducts().size();i++){
                String[] body;
                  body=obj.getproducts().get(i).toString().split("\\+");
                ProductModel p = new ProductModel(body[0].toString(), body[1].toString(), body[2].toString());
                prod.add(p);

            }
            }

    }
    });
if(prod.size()>0) {
    adapter = new ProductAdapter(prod);
    RecyclerView recview = findViewById(R.id.items_recycler_view);
    recview.setHasFixedSize(true);
    recview.setLayoutManager(new LinearLayoutManager(this));
    recview.setAdapter(adapter);
}else{
    Toast.makeText(getApplicationContext(),"this list is empty",Toast.LENGTH_LONG).show();
}
    }

и мой класс адаптера выглядит так:

public class ProductAdapter  extends RecyclerView.Adapter<ProductAdapter.ViewHolder> {

    private ArrayList<ProductModel> products;

    public ProductAdapter(ArrayList<ProductModel> product) {
        this.products = product;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = (View) LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_product, parent, false);

        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

        ProductModel prod = products.get(position);

        holder.name.setText(prod.getGetProductName());
        holder.description.setText(prod.getProductMarque());
        holder.qty.setText(prod.getProductQte());


    }

    @Override
    public int getItemCount() {
        if (products != null) {
            return products.size();
        } else {
            return 0;
        }
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        public final View view;
        public final TextView name;
        public final TextView description;
        public final TextView qty;

        public ViewHolder(View view) {
            super(view);
            this.view = view;
            name = view.findViewById(R.id.productsName);
            description = view.findViewById(R.id.marque);
            qty=view.findViewById(R.id.quantity);


        }
    }
}

Есть идеи, что не так?

Ответы [ 2 ]

1 голос
/ 16 июня 2020

Вам нужно добавить notifyDataSetChanged(), когда обратный вызов события завершен.

    @Override
    public void onEvent(@Nullable QuerySnapshot documentSnapshots, @Nullable FirebaseFirestoreException e) {
        assert documentSnapshots != null;
        for (DocumentChange document : documentSnapshots.getDocumentChanges()) {
        generalObject obj=document.getDocument().toObject(generalObject.class);
        for(int i=0;i<obj.getproducts().size();i++){
            String[] body;
              body=obj.getproducts().get(i).toString().split("\\+");
            ProductModel p = new ProductModel(body[0].toString(), body[1].toString(), body[2].toString());
            prod.add(p);

        }
        adapter.notifyDataSetChanged(); // <<<<<< here is the change
   }

Другое: условие if(prod.size()>0) слишком рано, так как оно не будет соответствовать, потому что данные получены фоновый поток, поэтому это условие никогда не будет выполнено. Измените эту часть на:

adapter = new ProductAdapter(prod);
RecyclerView recview = findViewById(R.id.items_recycler_view);
recview.setHasFixedSize(true);
recview.setLayoutManager(new LinearLayoutManager(this));
recview.setAdapter(adapter);

if (prod.size()==0) {
    Toast.makeText(getApplicationContext(),"this list is empty",Toast.LENGTH_LONG).show();
}
0 голосов
/ 16 июня 2020

Ваш запрос из Firebase выполняется асинхронно, поэтому данные запроса возвращаются и добавляются в список продуктов после того, как вы создали экземпляр адаптера.

Ваш оператор if не выполняется, потому что список продуктов фактически пуст, потому что этот код выполняется до того, как запрос вернется.

// This is false here because this block is getting executed before 
// the Firebase query returns the data. However your not seeing the 
// toast, because you are passing the wrong context. Toast takes 
// an activity context, not application context.

if(prod.size()>0) {
    adapter = new ProductAdapter(prod);
    RecyclerView recview = findViewById(R.id.items_recycler_view);
    recview.setHasFixedSize(true);
    recview.setLayoutManager(new LinearLayoutManager(this));
    recview.setAdapter(adapter);
}else{
    Toast.makeText(getApplicationContext(),"this list is empty",Toast.LENGTH_LONG).show();
}

Попробуйте немного изменить свой код, чтобы создать адаптер, затем добавьте данные, как только он вернется из запроса:

adapter = new ProductAdapter();
    RecyclerView recview = findViewById(R.id.items_recycler_view);
    recview.setHasFixedSize(true);
    recview.setLayoutManager(new LinearLayoutManager(this));
    recview.setAdapter(adapter);


products.whereEqualTo("IDliv","kITQ8wiPshsnWqHDlP5D").addSnapshotListener(new EventListener<QuerySnapshot>() {
        @Override
        public void onEvent(@Nullable QuerySnapshot documentSnapshots, @Nullable FirebaseFirestoreException e) {
            assert documentSnapshots != null;
            for (DocumentChange document : documentSnapshots.getDocumentChanges()) {
            generalObject obj=document.getDocument().toObject(generalObject.class);

            for(int i=0;i<obj.getproducts().size();i++){
                String[] body;
                  body=obj.getproducts().get(i).toString().split("\\+");
                ProductModel p = new ProductModel(body[0].toString(), body[1].toString(), body[2].toString());
                prodList.add(p);

            }

            // Tell the adapter we have new data that we want to add
            adapter.addNewData(prodList)

            }

    }
    });

Затем немного измените свой адаптер:

public class ProductAdapter  extends RecyclerView.Adapter<ProductAdapter.ViewHolder> {

    private ArrayList<ProductModel> products;

    public ProductAdapter() {
        this.products = new ArrayList<ProductModel>();
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = (View) LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_product, parent, false);

        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

        ProductModel prod = products.get(position);

        holder.name.setText(prod.getGetProductName());
        holder.description.setText(prod.getProductMarque());
        holder.qty.setText(prod.getProductQte());


    }

    @Override
    public int getItemCount() {
        if (products != null) {
            return products.size();
        } else {
            return 0;
        }
    }

    public void addNewData(data: List<ProductModel>) {
        this.products.clear();
        this.products.addAll(data);
        notifyDatasetChanged(); //This will tell the adapter we have new data and to re-inflate the views
    }
}
...