-1

good evening everyone, Ive been searching for a solution to an error android studio's log is sending using RecyclerView to show a JSON "product" list with retrofit.

I have already read the questions related to this error but im not able to find the right answer to my needs.

Android: RecyclerView: No adapter attached; skipping layout

No adapter attached; skipping layout recyclerview error

recyclerview No adapter attached; skipping layout

No adapter attached; skipping layout onCreateView()

This is de error log showed by android studio

RecyclerView: No adapter attached; skipping layout

RecyclerView: No adapter attached; skipping layout

Surface: getSlotFromBufferLocked: unknown buffer: 0xa3d9a700

OpenGLRenderer: endAllStagingAnimators on 0xa2b6bb00 (RippleDrawable) with handle 0xa200a310

java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $

For this proyect are been used this Classes and Layout files

"Producto" Class

public class Producto {

    @SerializedName("id")
    @Expose
    private int id;
    @SerializedName("name")
    @Expose
    private String name;
    @SerializedName("status")
    @Expose
    private String status;
    @SerializedName("price")
    @Expose
    private String price;
    @SerializedName("regular_price")
    @Expose
    private String regularPrice;
    @SerializedName("sale_price")
    @Expose
    private String salePrice;
    @SerializedName("price_html")
    @Expose
    private String priceHtml;
    @SerializedName("on_sale")
    @Expose
    private boolean onSale;
    @SerializedName("total_sales")
    @Expose
    private int totalSales;
    @SerializedName("purchase_note")
    @Expose
    private String purchaseNote;
    @SerializedName("categories")
    @Expose
    private List<Category> categories;
    @SerializedName("menu_order")
    @Expose
    private int menuOrder;


    /**
     *
     * @return
     * The id
     */
    public int getId() {
        return id;
    }

    /**
     *
     * @param id
     * The id
     */
    public void setId(int id) {
        this.id = id;
    }

    /**
     *
     * @return
     * The name
     */
    public String getName() {
        return name;
    }

    /**
     *
     * @param name
     * The name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     *
     * @return
     * The status
     */
    public String getStatus() {
        return status;
    }

    /**
     *
     * @param status
     * The status
     */
    public void setStatus(String status) {
        this.status = status;
    }

    /**
     *
     * @return
     * The price
     */
    public String getPrice() {
        return price;
    }

    /**
     *
     * @param price
     * The price
     */
    public void setPrice(String price) {
        this.price = price;
    }

    /**
     *
     * @return
     * The regularPrice
     */
    public String getRegularPrice() {
        return regularPrice;
    }

    /**
     *
     * @param regularPrice
     * The regular_price
     */
    public void setRegularPrice(String regularPrice) {
        this.regularPrice = regularPrice;
    }

    /**
     *
     * @return
     * The salePrice
     */
    public String getSalePrice() {
        return salePrice;
    }

    /**
     *
     * @param salePrice
     * The sale_price
     */
    public void setSalePrice(String salePrice) {
        this.salePrice = salePrice;
    }

    /**
     *
     * @return
     * The priceHtml
     */
    public String getPriceHtml() {
        return priceHtml;
    }

    /**
     *
     * @param priceHtml
     * The price_html
     */
    public void setPriceHtml(String priceHtml) {
        this.priceHtml = priceHtml;
    }

    /**
     *
     * @return
     * The onSale
     */
    public boolean isOnSale() {
        return onSale;
    }

    /**
     *
     * @param onSale
     * The on_sale
     */
    public void setOnSale(boolean onSale) {
        this.onSale = onSale;
    }

    /**
     *
     * @return
     * The totalSales
     */
    public int getTotalSales() {
        return totalSales;
    }

    /**
     *
     * @param totalSales
     * The total_sales
     */
    public void setTotalSales(int totalSales) {
        this.totalSales = totalSales;
    }

    /**
     *
     * @return
     * The purchaseNote
     */
    public String getPurchaseNote() {
        return purchaseNote;
    }

    /**
     *
     * @param purchaseNote
     * The purchase_note
     */
    public void setPurchaseNote(String purchaseNote) {
        this.purchaseNote = purchaseNote;
    }

    /**
     *
     * @return
     * The categories
     */
    public List<Category> getCategories() {
        return categories;
    }

    /**
     *
     * @param categories
     * The categories
     */
    public void setCategories(List<Category> categories) {
        this.categories = categories;
    }

    /**
     *
     * @return
     * The menuOrder
     */
    public int getMenuOrder() {
        return menuOrder;
    }

    /**
     *
     * @param menuOrder
     * The menu_order
     */
    public void setMenuOrder(int menuOrder) {
        this.menuOrder = menuOrder;
    }

}

"Category" Class (which matches with the private List<Category> categories; property)

public class Category {

    @SerializedName("id")
    @Expose
    private int id;
    @SerializedName("name")
    @Expose
    private String name;
    @SerializedName("slug")
    @Expose
    private String slug;

    /**
     *
     * @return
     * The id
     */
    public int getId() {
        return id;
    }

    /**
     *
     * @param id
     * The id
     */
    public void setId(int id) {
        this.id = id;
    }

    /**
     *
     * @return
     * The name
     */
    public String getName() {
        return name;
    }

    /**
     *
     * @param name
     * The name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     *
     * @return
     * The slug
     */
    public String getSlug() {
        return slug;
    }

    /**
     *
     * @param slug
     * The slug
     */
    public void setSlug(String slug) {
        this.slug = slug;
    }
}

Both Containanied as Arrays in this class called "JSONproducts"

public class JSONproducts {

    private Producto[] products;
    private Category[] categories;

    public Producto[] getProducts(){

        return products;
    }

    public Category[] getCategories(){
        return categories;
    }
}

Then The Request Interface called "LecturaProductos"

public interface LecturaProductos {

    @GET("Products")
    Call<JSONproducts> ListarProductos();

}

The data Adapter for the Recycler View called "Adaptador"

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

    private ArrayList<Producto> productos;
    private ArrayList<Category> categoria;

    public Adaptador(ArrayList<Producto> productos, ArrayList<Category> categoria){
        this.productos = productos;
        this.categoria = categoria;
    }

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

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(Adaptador.ViewHolder holder, int position) {
        holder.nom_pro_tv.setText(productos.get(position).getName());
        holder.id_pro_tv.setText(productos.get(position).getId());
        holder.cat_pro.setText(categoria.get(position).getName());

    }

    @Override
    public int getItemCount() {

        return productos.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder{
        private TextView nom_pro_tv, id_pro_tv, cat_pro;
        public ViewHolder(View itemView) {
            super(itemView);

            nom_pro_tv = (TextView)itemView.findViewById(R.id.nom_pro_tv);
            id_pro_tv = (TextView)itemView.findViewById(R.id.id_pro_tv);
            cat_pro = (TextView)itemView.findViewById(R.id.cat_pro_tv);
        }
    }
}

And the Activity Class "ListaProductos"

public class ListaProductos extends AppCompatActivity {

    private RecyclerView recyclerView;
    private ArrayList<Producto> product;
    private ArrayList<Category> category;
    private Adaptador adaptador;



    public static final String BASE_URL= "https://mydomain.com.mx/wp-json/wc/v1/";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_lista_productos);
        showView();

    }

    private void showView(){
        recyclerView = (RecyclerView)findViewById(R.id.prod_recycler_view);
        recyclerView.setHasFixedSize(true);
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        cargarJSON();

    }

    private void cargarJSON(){
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        final LecturaProductos producto = retrofit.create(LecturaProductos.class);
        Call<JSONproducts> productoCall = producto.ListarProductos();
        productoCall.enqueue(new Callback<JSONproducts>() {
            @Override
            public void onResponse(Call<JSONproducts> call, Response<JSONproducts> response) {

                JSONproducts jsonproducts = response.body();
                product = new ArrayList<>(Arrays.asList(jsonproducts.getProducts()));
                category = new ArrayList<>(Arrays.asList(jsonproducts.getCategories()));
                adaptador = new Adaptador(product, category);
                recyclerView.setAdapter(adaptador);
            }

            @Override
            public void onFailure(Call<JSONproducts> call, Throwable t) {
                Log.d("Error", t.getMessage());

            }
        });


    }
}

And the Layout XML files that are been used

RecyclerView Layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_lista_productos"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="mx.com.corpcap.elrollorepartidor.ListaProductos">

<android.support.v7.widget.RecyclerView
    android:id="@+id/prod_recycler_view"
    android:layout_height="match_parent"
    android:layout_width="match_parent"/></LinearLayout>

CardView Layout for the product list

<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/nom_pro_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textStyle="bold"
            android:textSize="16sp"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"/>

        <TextView
            android:id="@+id/id_pro_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/cat_pro_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>
</android.support.v7.widget.CardView>

Everything complies great and launches the app without an issue but when the information is tried to be accessed it sends the log messages quoted in the beginning of this question.

Thanks a Lot

Community
  • 1
  • 1

1 Answers1

0

A RecyclerView is not much use on it's own without an adapter providing the data it must display. So when a RecyclerView is initialized and placed in the layout but .setAdapter has not yet been called, the problem you're experiencing occurs. How about you take an empty list and use that to initialize the adapter and set it to your RecyclerView before you even send the network request. When you make the network request and get a response, simply clear the old values in the list, add new values and notify your adapter that the data in the list has changed. This should avoid the skipping layout problem, Alex.

Something like this:

private ArrayList<YourObjectClass> listOfYourObjects = new ArrayList<>();
.
.
.
SomeAdapter yourAdapter = new SomeAdapter(listOfYourObjects , context);
yourRecyclerView.setAdapter(yourAdapter);
.
.
.
onResponse:
list.clear();
//Let the adapter know the list is empty now
yourAdapter.notifyDataSetChanged();
//Fill in your list with values from server using a for/while loop etc.
//Again notify your adapter that the list has changed:
yourAdapter.notifyDataSetChanged();

Hope that helps.

Shahraiz T.
  • 338
  • 4
  • 13