简体   繁体   中英

RecyclerView not Displaying Items in Android Studio 3.5.3

I've trying to display database from Mysql to RecylerView but app not showing anything. There is no error in logcat. I got this tutorial from google and the original Project work fine. I just learn to implement in my code.

The build.gradle :

implementation "androidx.recyclerview:recyclerview-selection:1.1.0-beta01"
implementation 'com.android.volley:volley:1.1.1'
implementation 'com.github.bumptech.glide:glide:4.8.0'


Here is the XML code of activity_main.xml :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.skripsans.MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recylcerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:layout_editor_absoluteX="745dp"
        tools:layout_editor_absoluteY="-51dp"
        android:visibility="visible">
    </androidx.recyclerview.widget.RecyclerView>

</RelativeLayout>


product_list.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="8dp">

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="120dp"
            android:layout_height="90dp"
            android:padding="4dp" />

        <TextView
            android:id="@+id/textViewTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:layout_toRightOf="@id/imageView"
            android:text="Apple MacBook Air Core i5 5th Gen - (8 GB/128 GB SSD/Mac OS Sierra)"
            android:textAppearance="@style/Base.TextAppearance.AppCompat.Small"
            android:textColor="#000000" />

        <TextView
            android:id="@+id/textViewShortDesc"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/textViewTitle"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="5dp"
            android:layout_toRightOf="@id/imageView"
            android:text="13.3 Inch, 256 GB"
            android:textAppearance="@style/Base.TextAppearance.AppCompat.Small" />

        <TextView
            android:id="@+id/textViewRating"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/textViewShortDesc"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="5dp"
            android:layout_toRightOf="@id/imageView"
            android:background="@color/colorPrimary"
            android:paddingLeft="15dp"
            android:paddingRight="15dp"
            android:text="4.7"
            android:textAppearance="@style/Base.TextAppearance.AppCompat.Small.Inverse"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/textViewPrice"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/textViewRating"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="5dp"
            android:layout_toRightOf="@id/imageView"
            android:text="INR 56990"
            android:textAppearance="@style/Base.TextAppearance.AppCompat.Large"
            android:textStyle="bold" />

    </RelativeLayout>

</LinearLayout>


Product.java

package com.example.skripsans;

/**
 * Created by Belal on 10/18/2017.
 */

public class Product {
    private int id;
    private String title;
    private String shortdesc;
    private double rating;
    private double price;
    private String image;

    public Product(int id, String title, String shortdesc, double rating, double price, String image) {
        this.id = id;
        this.title = title;
        this.shortdesc = shortdesc;
        this.rating = rating;
        this.price = price;
        this.image = image;
    }

    public int getId() {
        return id;
    }

    public String getTitle() {
        return title;
    }

    public String getShortdesc() {
        return shortdesc;
    }

    public double getRating() {
        return rating;
    }

    public double getPrice() {
        return price;
    }

    public String getImage() {
        return image;
    }
}


ProductsAdapter.java

package com.example.skripsans;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;


import com.bumptech.glide.Glide;

import java.util.List;

/**
 * Created by Belal on 10/18/2017.
 */

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


    private Context mCtx;
    private List<Product> productList;

    public ProductsAdapter(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.product_list, null);
        return new ProductViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ProductViewHolder holder, int position) {
        Product product = productList.get(position);

        //loading the image
        Glide.with(mCtx)
                .load(product.getImage())
                .into(holder.imageView);

        holder.textViewTitle.setText(product.getTitle());
        holder.textViewShortDesc.setText(product.getShortdesc());
        holder.textViewRating.setText(String.valueOf(product.getRating()));
        holder.textViewPrice.setText(String.valueOf(product.getPrice()));
    }

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

    class ProductViewHolder extends RecyclerView.ViewHolder {

        TextView textViewTitle, textViewShortDesc, textViewRating, textViewPrice;
        ImageView imageView;

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

            textViewTitle = itemView.findViewById(R.id.textViewTitle);
            textViewShortDesc = itemView.findViewById(R.id.textViewShortDesc);
            textViewRating = itemView.findViewById(R.id.textViewRating);
            textViewPrice = itemView.findViewById(R.id.textViewPrice);
            imageView = itemView.findViewById(R.id.imageView);
        }
    }
}


MainActivity.java

package com.example.skripsans;

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

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 MainActivity extends AppCompatActivity {

    //this is the JSON Data URL
    //make sure you are using the correct ip else it will not work
    private static final String URL_PRODUCTS = "http://192.168.100.10/Api.php";

    //a list to store all the products
    List<Product> productList;

    //the recyclerview
    RecyclerView recyclerView;


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

        //getting the recyclerview from xml
        recyclerView = findViewById(R.id.recylcerView);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        //initializing the productlist
        productList = new ArrayList<>();

        //this method will fetch and parse json
        //to display it in recyclerview
        loadProducts();
    }

    private void loadProducts() {

        /*
         * Creating a String Request
         * The request type is GET defined by first parameter
         * The URL is defined in the second parameter
         * Then we have a Response Listener and a Error Listener
         * In response listener we will get the JSON response as a String
         * */
        StringRequest stringRequest = new StringRequest(Request.Method.GET, URL_PRODUCTS,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        try {
                            //converting the string to json array object
                            JSONArray array = new JSONArray(response);

                            //traversing through all the object
                            for (int i = 0; i < array.length(); i++) {

                                //getting product object from json array
                                JSONObject product = array.getJSONObject(i);

                                //adding the product to product list
                                productList.add(new Product(
                                        product.getInt("id"),
                                        product.getString("title"),
                                        product.getString("shortdesc"),
                                        product.getDouble("rating"),
                                        product.getDouble("price"),
                                        product.getString("image")
                                ));
                            }

                            //creating adapter object and setting it to recyclerview
                            ProductsAdapter adapter = new ProductsAdapter(MainActivity.this, productList);
                            recyclerView.setAdapter(adapter);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {

                    }
                });

        //adding our stringrequest to queue
        Volley.newRequestQueue(this).add(stringRequest);
    }
}

It's because you are setting the root layout and subsequent child elements heights to wrap_content . If you give a definitive size to your root layout height and each view below it to the inner most view that wraps content you should see the content. I am dealing with the same issue currently which lead me here. So far the best solution I have for showing child views that require a wrapped height in a recycler is some iffy math and size adjustment by passing new LayoutParams to the views I am wrapping in my adapters OnBindViewHolder() .

It happens because the view has no size until it's content is set in the OnBindViewHolder() , but your view was already inflated by the time you get there, so the layout manager measures the height of the empty element of wrapped height as 0 , the adapter inflates the view then proceeds to set their content in OnBindViewHolder() which doesn't trigger a re-draw. If you have enough child views in your recycler to scroll them off screen, they may also re-draw appropriately when scrolled back into view since they now have content and thus a measured height.

I have saw a few custom layout managers that override the getMeasuredHeight methods and such, but no such solutions worked for me and I ended up setting my content data in the viewHolder, then calling .measure() on the view that now has content and height. Afterwards I set the layout params of all elements with wrap_content for their height from a set of layout params that takes .getMeasuredHeight() from the inner most view where the data was set and re-measured.

This solution may also work for you if you really need to wrap the height, but it is a little more complicated and prone to bugs in my implementation since the inner most view I am wrapping is a TextView with an unknown number of lines until it is set. I use some simple math to calculate how many rows the input String will take up then multiply that by the measures height of the TextView. This is sketchty practice as different devices of varying screen ratios, sizes and typeFace can result in varying number of lines in the TextView which is impossible to account for on all devices. Less complicated views may do well with this solution, but using a GeometryReader or the like could improve it. I just only started working on this issue in my project today, so I haven't really had a chance to flush it out, I just got it to a usable state for my test device so I can keep working on the surrounding features which will make it easier to test variations of my recycler the complete. I need to get the parts that are responsible for making the data these recyclers are populated with working so I can make test variations of possible data and user devices, then I can find a better solution or fine tune this one to fit my needs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM