-1

My application is not producing the information that it has been requested in the java files. It was hoped that the app would produce a recycler view of information that is being stored in a phpMyAdmin database.

However, all I am getting is a blank/empty activity.

The LogCat is producing an error that is to do with the RecyclerView, however, I am not sure how to get around this error/know if this is the error that is causing the blank activity.

LogCat

02-07 11:28:55.936 5622-5622/com.example.xxxx.myapplication E/RecyclerView: No adapter attached; skipping layout

Adapter

package com.example.benchalmers.myapplication;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

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


    private Context mCtx;
    private List<Product> productList;

    public ProductAdapter(Context mCtx, List<Product> productList) {
        this.mCtx = mCtx;
        this.productList = productList;
    }

    @Override
    public ProductViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        LayoutInflater inflater = LayoutInflater.from(mCtx);
        View view = inflater.inflate(R.layout.list_layout, null);
        return new ProductViewHolder(view);

    }

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

        Product product = productList.get(position);

        holder.textViewType.setText(product.getType());
        holder.textViewProperty.setText(product.getProperty());
        holder.textViewMoreInfo.setText(String.valueOf(product.getMoreInfo()));
        holder.textViewDate.setText(String.valueOf(product.getDate()));

        //holder.imageView.setImageDrawable(mCtx.getResources().getDrawable(product.getImage()));
    }

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

    class ProductViewHolder extends RecyclerView.ViewHolder {

        ImageView imageView;
        TextView textViewType, textViewProperty, textViewMoreInfo, textViewDate;

        public ProductViewHolder(View itemView) {
            super(itemView);

            imageView = itemView.findViewById(R.id.imageView);
            textViewType = itemView.findViewById(R.id.textViewType);
            textViewProperty = itemView.findViewById(R.id.textViewProperty);
            textViewMoreInfo = itemView.findViewById(R.id.textViewMoreInfo);
            textViewDate = itemView.findViewById(R.id.textViewDate);

        }
    }
}

Activity

package com.example.benchalmers.myapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.Toast;

import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

public class Maintenance extends AppCompatActivity {

    private static final String PRODUCT_URL = "http://192.168.64.2/MyApi/api.php";

    RecyclerView recyclerView;
    private ProductAdapter adapter;

    List<Product> productList;

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

        productList = new ArrayList<>();

        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        this.adapter = new ProductAdapter(this, productList);
        recyclerView.setAdapter(adapter);

        loadProducts ();

    }

    private void loadProducts () {

        StringRequest stringRequest = new StringRequest(Request.Method.GET, PRODUCT_URL,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        try {
                            JSONArray products  =new JSONArray(response);

                            for (int i = 0; i<products.length(); i++){

                                JSONObject productObject = products.getJSONObject(i);

                                int maintenance_id = productObject.getInt("maintenance_id");
                                String type = productObject.getString("type");
                                String property = productObject.getString("property");
                                String more_info = productObject.getString("more_info");
                                Double date = productObject.getDouble("date");

                                Product product = new Product(maintenance_id, type, property, more_info, date);
                                productList.add(product);

                            }

                            adapter = new ProductAdapter(Maintenance.this, productList);
                            recyclerView.setAdapter(adapter);

                        } catch (JSONException e) {
                            e.printStackTrace();
                        }

                    }
                },

                new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

                Toast.makeText(Maintenance.this, error.getMessage(), Toast.LENGTH_SHORT).show();

                    }
                });

        Volley.newRequestQueue(this).add(stringRequest);

    }
}

I have not attached any Java files at this stage, as I do not believe that they are the issue here.

I have looked at various threads on Stack, but none of which seem to do the job.

Any guidance would be appreciated!

Kali Ma
  • 125
  • 2
  • 16
  • Could you post your RecyclerView Adapter & Activity code – Abhishek kumar Feb 07 '18 at 16:38
  • Like it says. You are not attaching an adapter with the `RecyclerView`. Can you add the activity here? – Napster Feb 07 '18 at 16:38
  • Adapter code added. – Kali Ma Feb 07 '18 at 16:39
  • Add the activity code where you add the adapter. This error is not from inside the adapter – Napster Feb 07 '18 at 16:40
  • Attach Activity code too @KaliMa – Abhishek kumar Feb 07 '18 at 16:40
  • Apologies, misunderstood. Added. – Kali Ma Feb 07 '18 at 16:41
  • 1
    So you see how you are attaching the adapter inside the `StringRequest`? that is an `AsyncTask` which completes later. What you need to do is attach an empty adapter where you are setting the `RecyclerView` properties and then update the data inside the adapter later once the request completes – Napster Feb 07 '18 at 16:43
  • Possible duplicate of [recyclerview No adapter attached; skipping layout](https://stackoverflow.com/questions/29141729/recyclerview-no-adapter-attached-skipping-layout) – Zoe Feb 07 '18 at 16:44
  • Put Log.e("List_Size"," "+productList.size()); below of adapter = new ProductAdapter(Maintenance.this, productList); on your Activity and check the size of the list – Abhishek kumar Feb 07 '18 at 16:45
  • This is off context but using JSONArray request would be better compared to StringRequest, as you are getting your response back in JSONArray format – kukroid Feb 07 '18 at 16:49

1 Answers1

0

As the error message says, you did not bind any Adapter to the RecyclerView so It cannot display anything and "skips the layout"

When you create an app with a RecyclerView, and you have written an Adapter, then you have to also attach that Adapter to the RecyclerView, which would something like this in your code:

private ProductAdapter adapter;

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

    productList = new ArrayList<>();

    recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    this.adapter = new ProductAdapter(this, productList);
    recyclerView.setAdapter(adapter)

    loadProducts ();

}

For more information about the RecyclerView, see this page from Android Developers.

Note, that in loadProducts();, after the request completes, you must not reinstantiate your Adapter but instead call this.adapter.notifyDataSetChanged();.

Twometer
  • 1,561
  • 2
  • 16
  • 24
  • Could anyone who casts a downvote, please explain *why* you downvoted? Thanks. – Twometer Feb 07 '18 at 16:50
  • Without Api call without set data into pojo class , if you call Adapter it will send null list value to the Adapter class by constructor. – Abhishek kumar Feb 07 '18 at 16:52
  • @Abhishekkumar It does *not* send a null list to the adapter, because the list has beeen initialized with `new ArrayList<>();` before. When you update that, you have to call `notifyDataSetChanged()` to the Adapter, and then the UI will reflect the changes. At best, the ArrayList would have been declared within the Adapter, but that's probably just a design issue. – Twometer Feb 07 '18 at 16:54
  • According to your code first it will perform ProductAdapter adapter = new ProductAdapter(this, productList); recyclerView.setAdapter(adapter) then call loadProducts (); – Abhishek kumar Feb 07 '18 at 16:56
  • @Abhishekkumar That does not matter, because `loadProducts()` issues an asynchronous Request anyway. – Twometer Feb 07 '18 at 16:57
  • @Twometer You answer seems to have removed the error from the LogCat, however, no information (from the DB) appears on the application. No errors appearing in the LogCat. – Kali Ma Feb 07 '18 at 16:58
  • @KaliMa see my updated answer, I've forgot a note to make the UI update. – Twometer Feb 07 '18 at 16:59
  • check by log is your pojo class have data or not @KaliMa – Abhishek kumar Feb 07 '18 at 17:03
  • I'm not sure what you mean @Abhishekkumar. Can you clarify further? – Kali Ma Feb 07 '18 at 17:04
  • Activity updated with your suggestions @Twometer. However, still nothing showing on the emulator. – Kali Ma Feb 07 '18 at 17:06
  • @KaliMa In your `ProductAdapter` you have to also override `getItemCount` to return your list size, as it returns 0 when not specified. – Twometer Feb 07 '18 at 17:10
  • @Twometer Is this not what is happening here in my ProductAdapter: `@Override public int getItemCount() { return productList.size(); } class ProductViewHolder extends RecyclerView.ViewHolder { ImageView imageView; TextView textViewType, textViewProperty, textViewMoreInfo, textViewDate;` – Kali Ma Feb 07 '18 at 17:14
  • Oh, oops sorry I didn't see that, of course you're doing just that. What you can try now is adding a method `add` to your Adapter. Then use that add method in your request callback instead of the `add` method of the original list. The problem could also be that Java is pass-by-value and therefore the list in the adapter is not updated when you update the list in the Activity. – Twometer Feb 07 '18 at 17:17
  • Problem is only with your list – Abhishek kumar Feb 07 '18 at 17:24
  • @KaliMa see my comment for a possible solution, I forgot the @ mention – Twometer Feb 07 '18 at 17:38
  • Thanks for this @Twometer. I'm quite new at all this so not sure how to implement it. – Kali Ma Feb 07 '18 at 17:39
  • @KaliMa add `public void addProduct(Product p) {productList.add(p);}` to your **Adapter**, and then in `onResponse()`, instead of `productList.add(product);`, you write `adapter.addProduct(product);` – Twometer Feb 07 '18 at 21:06