0

I have a fragment that is going to show a list in recycler view from a list of objects. My fragment class is as following:

// A simple {@link Fragment} subclass.
public class RedditListFragment extends Fragment implements AsyncResponse {

    AsyncResponse asyncResponse;
    private RecyclerView mRecyclerView;
    private RedditAdapter mAdapter;;
    private List<RedditObject> objectList;
    Parser parse;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        executeAsyncTask();

        View view = inflater.inflate(R.layout.fragment_reddit_list, container, false);
        mRecyclerView = (RecyclerView) view.findViewById(R.id.reddit_list_view);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

        updateUI();

        // Inflate the layout for this fragment
        return view;
    }

    public void executeAsyncTask(){
        DownLoadRawData downLoadRawData = new DownLoadRawData();
        downLoadRawData.delegate = this;
        downLoadRawData.execute("https://www.reddit.com/r/Showerthoughts/.json");


        // Log.d("ERR", " TEXT WAS "  + jsonTEXT);
    }

    @Override
    public void processFinish(String output) {
        Log.d("TAG", "What is happening!");
        Log.d("TAG", "process finished reached");
        parse = new Parser(output);
        this.objectList = parse.getRedditObjectsList();
        Log.d("TAG", "OBJECT LIST WAS" + objectList.toString());
        Log.d("TAG", "The List to STring is " + parse.getRedditObjectsList().toString());

    }

    public void updateUI(){
        List<RedditObject> listOfRedditObject = objectList;

        mAdapter = new RedditAdapter(listOfRedditObject);
        mRecyclerView.setAdapter(mAdapter);
    }

    private class RedditHolder extends RecyclerView.ViewHolder {

        private TextView mTextView;

        public RedditHolder(View itemView) {
            super(itemView);
            mTextView = (TextView) itemView;  //by casting itemView to a TextView, this forces client to pass text view
        }
    }

    private class RedditAdapter extends RecyclerView.Adapter<RedditHolder>{

        private List<RedditObject> mListOfRedditObjects;

        public RedditAdapter(List<RedditObject> listOfRedditObject){
           mListOfRedditObjects = listOfRedditObject;
        }

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

            LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
            View view = layoutInflater.inflate(R.layout.single_reddit_listing, parent, false);  
            return new RedditHolder(view);
        }

        @Override
        public void onBindViewHolder(RedditHolder holder, int position) {
                RedditObject redditObject = mListOfRedditObjects.get(position);
                holder.mTextView.setText(redditObject.getmTitle());
        }

        @Override
        public int getItemCount() {
         //   Log.d("TAG ", "In the adapter and can confirm" + mListOfRedditObjects.size());
            return mListOfRedditObjects.size();
        }
    }
}

In my updateUI(), I have verified that the objectList List<> is not null. Yet, for some reason at the bottom of my code, where Android gets the size of the array in getItemsCount(); I always get this error:

12-15 21:00:11.532 26097-26097/com.example.ridhwaan.redditforfaez E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.ridhwaan.redditforfaez, PID: 26097
    java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
    at com.example.ridhwaan.redditforfaez.RedditListFragment$RedditAdapter$override.getItemCount(RedditListFragment.java:144)
    at com.example.ridhwaan.redditforfaez.RedditListFragment$RedditAdapter$override.access$dispatch(RedditListFragment.java)
    at com.example.ridhwaan.redditforfaez.RedditListFragment$RedditAdapter.getItemCount(RedditListFragment.java:0)
    at android.support.v7.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:3289)
    at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3186)
    at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3632)
    at android.view.View.layout(View.java:17522)
    at android.view.ViewGroup.layout(ViewGroup.java:5612)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
    at android.view.View.layout(View.java:17522)
    at android.view.ViewGroup.layout(ViewGroup.java:5612)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
    at android.view.View.layout(View.java:17522)
    at android.view.ViewGroup.layout(ViewGroup.java:5612)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
    at android.view.View.layout(View.java:17522)
    at android.view.ViewGroup.layout(ViewGroup.java:5612)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
    at com.android.internal.policy.DecorView.onLayout(DecorView.java:724)
    at android.view.View.layout(View.java:17522)
    at android.view.ViewGroup.layout(ViewGroup.java:5612)
    at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2342)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2069)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1246)
    at (more exception lines)

I tried fixing this for 2 days now by using Log statements and debugging. If you need any further information I can give it to you.

Here is the Async Task class:

public class DownLoadRawData extends AsyncTask<String, Void, String> {

    private String mFileContents;
    public  AsyncResponse delegate = null;

    public String getmFileContents() {
        return mFileContents;
    }

    @Override
    protected String doInBackground(String... strings) {
        mFileContents = downloadRawJSON(strings[0]);

        return mFileContents;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        delegate.processFinish(result);
        Log.d("TAG", "RESULT" + result);
    }

    private String downloadRawJSON(String urlSpec){
        Log.d("TAG", "DOWNLOADING" + "  " + urlSpec);
        StringBuilder sb = new StringBuilder();

        try{
            Log.d("TAG", "ENTETRED TRY BLOCK");
            URL url = new URL(urlSpec);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            int response = conn.getResponseCode();
            Log.d("TAG" , "RESPONSE CODE" + "  " + response);
            InputStream is = conn.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);

            int charRead;
            char[] buffer = new char[500];

            while(true){
                charRead = isr.read(buffer); // returns number read + reads into parameter

                if(charRead <= 0){
                    Log.d("TAG","BROKE");
                    break;
                }

                sb.append(String.copyValueOf(buffer,0,charRead));

            }
            return sb.toString();

        }catch (Exception e){
            Log.d("TAG", "FATAL ERROR" + " BECASE   " + e.getMessage());
            e.printStackTrace();
        }

        Log.d("TAG" , " ERROR NO DATA");
        return null;
    }
}

In this, processFinish is a call back method.

rupinderjeet
  • 2,984
  • 30
  • 54
Ridhwaan
  • 57
  • 8
  • I am assuming that the "objectList" is being set in the "DownLoadRawData" Asynctask? move your updateUI call in the onPostExecute of DownLoadRawData. That will hopefully fix it. Otherwise, please post the code for the asynctask as well – Hahn Dec 16 '16 at 02:19
  • I added AsyncTask. – Ridhwaan Dec 16 '16 at 02:34
  • Ok. remove the updateUi from onCreateView. Then at the end of the processFinish callback, call updateUi. – Hahn Dec 16 '16 at 02:38
  • Worked perfectly thank you. – Ridhwaan Dec 23 '16 at 23:35

2 Answers2

2

The Asynctask gets executed on the background thread,and the updateUI() gets executed on the main thread. In this case, your "updateUI()" method is being executed before the Asynctask DownLoadRawData completes its execution. Hence your objectList is still null.

Move the updateUI() method invocation to the onPostExecute() of the DownLoadRawData. That should clear this error.

Also whenever you create a data structure its always good to initialise the object. In your case :

private List<RedditObject> objectList=new List<RedditObject>();
Akhil Soman
  • 2,077
  • 2
  • 17
  • 30
1

you need to call your updateUI(); method after the line this.objectList = parse.getRedditObjectsList(); and also modify your updateUI method

public void updateUI(){

    listOfRedditObject = objectList;

    if(listOfRedditObject == null) // to avoid nullpointer exception in case if object list is null
    {
        List<RedditObject> listOfRedditObject = new ArrayList<>();
    }

        mAdapter = new RedditAdapter(listOfRedditObject);
        mRecyclerView.setAdapter(mAdapter);
    }