简体   繁体   中英

My RecyclerView in fragment stays blank even when it's populated

I have the following problem with RecyclerView on Android:

Whenever I try to open the fragment with the RecyclerView, it stays blank. My ArrayList mList isn't empty, it contains data (I tested it).

I tried many things to fix this problem, but I'm a beginner, so I don't really know where the problem is.

The RecyclerView should display a list of products. I think there is a problem with my adapter or maybe the xml file fragment_list doesn't show up properly? I don't really know.

My ListAdaper class:

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;

public class ListAdapter extends 
RecyclerView.Adapter<ListAdapter.ListViewHolder> {

private Context mContext;
private ArrayList<Item> mList;

public ListAdapter(Context context, ArrayList<Item> list) {

    mContext = context;
    mList = list;

}

@NonNull
@Override
public ListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(mContext).inflate(R.layout.list_item, parent, false);
    return new ListViewHolder(v);
}

@Override
public void onBindViewHolder(@NonNull ListViewHolder holder, int position) {
    Item currentItem = mList.get(position);

    holder.textViewName.setText(currentItem.getName());
    holder.textViewRegion.setText(currentItem.getRegion());
}

@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);
}

public static class ListViewHolder extends RecyclerView.ViewHolder {

    public CardView cardView;
    public TextView textViewName;
    public TextView textViewRegion;

    public ListViewHolder(@NonNull View itemView) {
        super(itemView);
        cardView = itemView.findViewById(R.id.cardview);
        textViewName = itemView.findViewById(R.id.item_name);
        textViewRegion = itemView.findViewById(R.id.item_region);
    }
}

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

...my ListFragment class:

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Iterator;


public class ListFragment extends Fragment {

private RecyclerView mRecyclerView;
private ListAdapter mListAdapter;
private ArrayList<Item> mList;
private RequestQueue mRequestQueue;
private Context mContext;


@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View rootview = inflater.inflate(R.layout.fragment_list, container, false);

    mRecyclerView = rootview.findViewById(R.id.recycler_view);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
    mRecyclerView.setHasFixedSize(true);
    parseJSON();
    mRecyclerView.setAdapter(mListAdapter);
    mRecyclerView.setItemAnimator(new DefaultItemAnimator());
    return rootview;
}

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
}

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    mContext = context;
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mList = new ArrayList<>();
    mListAdapter = new ListAdapter(mContext, mList);
    mRequestQueue = Volley.newRequestQueue(mContext);

}


private void parseJSON() {

    JsonObjectRequest request = new JsonObjectRequest("http://my_ip/sestavsisvujsvetweb/api/seznammagnetek", null, new Response.Listener<JSONObject>() {

        @Override
        public void onResponse(JSONObject response) {
            JSONObject magnetky = response;
            try {

                Iterator keys = magnetky.keys();
                while (keys.hasNext()) {
                    Object key = keys.next();
                    JSONObject value = magnetky.getJSONObject((String) key);
                    String monumentnumber = value.getString("monumentid");
                    String monumentname = value.getString("name");
                    String monumentregion = value.getString("region");
                    mList.add(new Item(monumentnumber, monumentname, monumentregion));
                }

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

        }
    }

            , new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            error.printStackTrace();
        }
    });
    if (request != null) {
        mRequestQueue.add(request);
    }

}

}

.....and my Item model class:

public class Item {

private String name;
private String number;
private String region;

public Item(String number, String name, String region) {
    this.name = name;
    this.number = number;
    this.region = region;
}
public String getName() {
    return name;
}
public String getRegion() {
    return region;
}
public String getNumber() { return number; }
}

Thanks for help, if I didn't include something important please do let me know :)

Update: I tried adding mListAdapter.notifyDataSetChanged(); and it seems so work, but I get this error in the log:

2019-08-21 19:46:16.947 5542-5542/com.example.app E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.app, PID: 5542
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
    at com.example.app.ListAdapter.onBindViewHolder(ListAdapter.java:38)
    at com.example.app.ListAdapter.onBindViewHolder(ListAdapter.java:15)

........and some other stuff

Remove this line:

    mRecyclerView.setHasFixedSize(true);

Since you are loading data asynchronously, your data size is 0 when you set the adapter. Because you are setting it to fixed size, RecyclerView won't update its size when items change.

From documentation on setHasFixedSize() :

RecyclerView can still change its size based on other factors (eg its parent's size) but this size calculation cannot depend on the size of its children or contents of its adapter (except the number of items in the adapter).

You can also set the adapter after loading the data . It should work as well.

您需要通知适配器有关数据集更改的信息。请在onResponse()onResponse()以下代码

mListAdapter.notifyDataSetChanged();

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