I have this json:
{
"title": "Sample title of this json",
"excerpt": "Sample excerpt for the json. Random alphabets: yehodjjd uushdkjnjk jghdd",
"tags": {
"chlorine": {
"name": "chlorine",
"post_count": 32,
},
"flourine": {
"name": "flourine",
"post_count": 78,
}
},
}
"title", "excerpt" and "tags" are known keys. They are always "title", "excerpt" and "tags". On other hand, the JsonObjects in "tags" are dynamic. Let me explain.
The number of the objects are two in this json, but it might be one object, two or even seven. There are just "chlorine" and ""flourine" here but the objects might be just anything. So in other words I don't know before hand the objects in the "tags".
What I want to do is display "title" and "except" in a TextView, so far that is working.
I also want to display the dynamic objects in "tags" in a kind of dynamic list, I chose RecyclerView and this seems not to be working. The objects is being parsed quite alright but the problem is displaying it.
These are my codes:
fragment_details.xml
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:fillViewport="true"
android:id="@+id/details_layout"
tools:context=".Fragment.DetailsFragment">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/details_relat">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:id="@+id/dpost_title"
android:visibility="gone"
android:layout_margin="5dp"
android:textStyle="bold"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/dpost_title"
android:textColorLink="@color/textlink"
android:visibility="invisible"
android:id="@+id/dpost_content"
android:layout_margin="5dp"/>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tag_cat_recy"/>
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
tags_cats_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="@+id/tag_cat_lin"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tag_cat_text"/>
</LinearLayout>
TagCatItem
public class TagCatItem {
private String tagCatName;
private int tagCatCount;
public String getTagCatName() {
return tagCatName;
}
public void setTagCatName(String tagCatName) {
this.tagCatName = tagCatName;
}
public int getTagCatCount() {
return tagCatCount;
}
public void setTagCatCount(int tagCatCount) {
this.tagCatCount = tagCatCount;
}
}
DetailsFragment
public class DetailsFragment extends Fragment{
private List<TagCatItem> mTagCatItem;
RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
LinearLayoutManager mLayoutManager;
TextView postTitle, postContent;
public DetailsFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "onCreateView called");
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_details, container, false);
postTitle = (TextView)view.findViewById(R.id.dpost_title);
postContent = (TextView) view.findViewById(R.id.dpost_content);
mRecyclerView = (RecyclerView) view.findViewById(R.id.tag_cat_recy);
getPost();
return view;
}
private void getPost() {
Log.d(TAG, "getPost called");
JsonObjectRequest postDetails = new JsonObjectRequest(Method.GET, url, null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.d(TAG, "onResponse for getPOst called");
parseJson(response);
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "onErrorResponse for getPost called");
}
});
//Creating requestqueue
RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
//Adding request queue
requestQueue.add(postDetails);
}
private void parseJson(JSONObject object) {
Log.d(TAG, "Parsing Json");
try {
mTitle = String.valueOf(Html.fromHtml(object.getString("title")));
postTitle.setText(mTitle);
mLayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new TagCatAdapter(mTagCatItem, getActivity());
mRecyclerView.setAdapter(mAdapter);
String content = object.getString("content");
postContent.setText(content);
JSONObject tags = object.getJSONObject("tags");
Iterator tagsObjs = tags.keys();
while (tagsObjs.hasNext()) {
// loop to get dynamic tag objects
String tagObj = (String) tagsObjs.next();
Log.d(TAG, "tagObj is " + tagObj);
JSONObject tagObjDetails = tags.getJSONObject(tagObj);
TagCatItem tagCatItem = new TagCatItem();
String tagName = tagObjDetails.getString("name");
tagCatItem.setTagCatName(tagName);
Log.d(TAG, "Tag Name is " + tagName);
int tagDetailsNum = tagObjDetails.getInt("post_count");
tagCatItem.setTagCatCount(tagDetailsNum);
Log.d(TAG, "Number of posts " + tagDetailsNum);
mTagCatItem.add(tagCatItem);
mAdapter.notifyItemRangeChanged(0, mAdapter.getItemCount());
}
//Unhiding views
postTitle.setVisibility(View.VISIBLE);
postContent.setVisibility(View.VISIBLE);
}
} catch (JSONException w) {
w.printStackTrace();
}
}
}
**TagCatAdapter**
public class TagCatAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context mContext;
private List<TagCatItem> mTagCatItems;
public TagCatAdapter(List<TagCatItem> tagCatItems, Context context) {
super();
this.mTagCatItems = tagCatItems;
this.mContext = context;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.tags_cats_item, parent, false);
return new TextViewHolder(v);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
TagCatItem tagCatItem = mTagCatItems.get(position);
((TextViewHolder) holder).tagCatName.setText(tagCatItem.getTagCatName());
}
public class TextViewHolder extends RecyclerView.ViewHolder{
public TextView tagCatName;
public TextViewHolder(View mView) {
super(mView);
tagCatName = (TextView) view.findViewById(R.id.tag_cat_text);
}
}
@Override
public int getItemCount() {
return mTagCatItems.size();
}
}
StackTrace
07-01 20:06:25.563 21725-21725/com.ozuf.poster E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.ozuf.poster, PID: 21725
java.lang.NullPointerException: Attempt to invoke interface method 'boolean java.util.List.add(java.lang.Object)' on a null object reference
at com.ozuf.poster.Fragment.DetailsFragment.parseJson(DetailsFragment.java:492)
at com.ozuf.poster.Fragment.DetailsFragment.access$600(DetailsFragment.java:73)
at com.ozuf.poster.Fragment.DetailsFragment$7.onResponse(DetailsFragment.java:395)
at com.ozuf.poster.Fragment.DetailsFragment$7.onResponse(DetailsFragment.java:391)
at com.android.volley.toolbox.JsonRequest.deliverResponse(JsonRequest.java:65)
at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5910)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1405)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1200)
From the stacktrace, Line 492 is mTagCatItem.add(tagCatItem);
Line 73 is public class DetailsFragment extends Fragment {
Line 395 is parseJson(response);
Line 391 is new Response.Listener<JSONObject>() {
Attempted Solution
I have tried moving:
mLayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new TagCatAdapter(mTagCatItem, getActivity());
mRecyclerView.setAdapter(mAdapter);
to onCreateView
of DetailsFragment but it crashed with the error that I am trying to call mTagCatItems.size() on a null object reference.