-1

I have an RSS feed, which when I've changed the source of the feed it crashes with an error:

Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference.

I've looked through my new link and to my logic it should still work (all the nodes are pretty much the same etc) but for some reason it doesn't.

Ideally I'd like to use both links together. Which is possible with my code as I've used two links together before.

Any ideas why this isn't working?

New link (that I'm trying to use): https://feeds.finance.yahoo.com/rss/2.0/headline?s=yhoo,msft,tivo&region=US&lang=en-US

Old link: https://www.bloomberg.com/politics/feeds/site.xml

RSSFeed.java:

public class ReadRss extends AsyncTask<Void,Void,Void>{
ArrayList<FeedItem>feedItems;
RecyclerView recyclerView;
Context context;
static ArrayList<String>address;

static {
    address=new ArrayList<>();
   address.add("http://finance.yahoo.com/rss/headline?s=yhoo,msft,tivo");
   //address.add("https://www.bloomberg.com/politics/feeds/site.xml");
    //address.add("https://www.bloomberg.com/feeds/podcasts/etf_report.xml");
}

ProgressDialog progressDialog;
URL url;
public ReadRss(Context context, RecyclerView recyclerView){
    this.recyclerView=recyclerView;
    this.context=context;
    progressDialog=new ProgressDialog(context);
    progressDialog.setMessage("Loading...");
}

@Override
protected void onPreExecute() {
    progressDialog.show();
    super.onPreExecute();
}

@Override
protected void onPostExecute(Void aVoid) {

    super.onPostExecute(aVoid);
    progressDialog.dismiss();
    MyAdapter adapter=new MyAdapter(context,feedItems);
    recyclerView.setLayoutManager(new LinearLayoutManager(context));
    recyclerView.addItemDecoration(new VerticalSpace(50));
    recyclerView.setAdapter(adapter);
}

@Override
protected Void doInBackground(Void... params) {
    ProcessXml(Getdata());
    return null;
}

private void ProcessXml(ArrayList<Document> data) {
    if (data != null) {
        feedItems = new ArrayList<>();
        for (Document doc : data) {
            Element root = doc.getDocumentElement();
            Node channel = root.getChildNodes().item(0);
            NodeList items = channel.getChildNodes();
            for (int i = 0; i < items.getLength(); i++) {
                Node currentchild = items.item(i);
                if (currentchild.getNodeName().equalsIgnoreCase("item")) {
                    FeedItem item = new FeedItem();
                    NodeList itemchilds = currentchild.getChildNodes();
                    for (int j = 0; j < itemchilds.getLength(); j++) {
                        Node current = itemchilds.item(j);
                        if (current.getNodeName().equalsIgnoreCase("title")) {
                            item.setTitle(current.getTextContent());
                        } else if (current.getNodeName().equalsIgnoreCase("description")) {
                            item.setDescription(current.getTextContent());
                        } else if (current.getNodeName().equalsIgnoreCase("pubDate")) {
                            item.setPubDate(current.getTextContent());
                        } else if (current.getNodeName().equalsIgnoreCase("link")) {
                            item.setLink(current.getTextContent());
                        }

                    }
                    feedItems.add(item);
                    Log.d("itemTitle", item.getTitle());
                    Log.d("itemDescription", item.getTitle());
                    Log.d("itemLink", item.getTitle());
                    Log.d("itemPubDate", item.getTitle());
                }
            }
        }
    }
}

public ArrayList<Document> Getdata(){
    ArrayList<Document> documents = new ArrayList<>();
    for (String addr: address) {
        try {
            url = new URL(addr);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            InputStream inputStream = connection.getInputStream();
            DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = builderFactory.newDocumentBuilder();
            Document xmlDoc = builder.parse(inputStream);
            documents.add(xmlDoc);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    return documents;
}

}

MyAdapter.java:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>{
    ArrayList<FeedItem>feedItems;
    Context context;
     public MyAdapter(Context context,ArrayList<FeedItem>afeedItems){
        this.feedItems= new ArrayList<FeedItem>(afeedItems);
        this.context=context;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view= LayoutInflater.from(context).inflate(R.layout.custum_row_news_item,parent,false);
        MyViewHolder holder=new MyViewHolder(view);
        return holder;

    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        YoYo.with(Techniques.FadeIn).playOn(holder.cardView);
        final FeedItem current=feedItems.get(position);
        holder.Title.setText(current.getTitle());
        holder.Description.setText(current.getDescription());
        holder.Date.setText(current.getPubDate());
        holder.cardView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(context, NewsDetails.class);
                intent.putExtra("Link", current.getLink());
                context.startActivity(intent);
            }
        });

    }

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

    public class MyViewHolder extends RecyclerView.ViewHolder {
        TextView Title,Description,Date;
        CardView cardView;
        public MyViewHolder(View itemView) {
            super(itemView);
            Title= (TextView) itemView.findViewById(R.id.title_text);
            Description=(TextView) itemView.findViewById(R.id.description_text);
            Date=(TextView) itemView.findViewById(R.id.date_text);
            cardView= (CardView) itemView.findViewById(R.id.cardview);
        }
    }
}
halfer
  • 19,824
  • 17
  • 99
  • 186
Joe
  • 253
  • 1
  • 7
  • 20
  • @JoeC I did my research before hand, the solution in the question didn't fix my problem. Cheers. – Joe Apr 23 '17 at 21:56
  • The solution to get rid of an NPE is **always** to find which is the object you are using before instancing it. – Phantômaxx Apr 23 '17 at 22:34
  • I've tried to do what that answer suggests, with no luck @Rotwang . This is why I asked the question. – Joe Apr 23 '17 at 22:37
  • Try to find which is the non instanced object. The logcat will help to narrow your research for the culprit. – Phantômaxx Apr 23 '17 at 22:39

2 Answers2

2

When you assign an ArrayList to another one like this :

this.feedItems=feedItems;

They both have same refrence to an arraylist, instead of direct assigning, you should copy the list values from feedItems to this.feedItems, for example :

ArrayList<FeedItem> newFeedItems = new ArrayList<FeedItem>(oldFeedItems);

After executing of asynctask finished, the object feedItems of asynctask class will be freed and then feedItems of your adapter class also will be referenced to a null value

That error says that the feedItems.size() method invoked from a null reference object

Edit :

Constructor of your adapter must be like this :

public MyAdapter(Context context,ArrayList<FeedItem>afeedItems){
    this.feedItems= new ArrayList<FeedItem>(afeedItems);
    this.context=context;
}

As another suggestion don't use exactly same names for multiple variables

Mahmoud_Mehri
  • 1,643
  • 2
  • 20
  • 38
  • Thanks for the answer and the info! I didn't know that. So, I should copy the values (ArrayList newFeedItems = new ArrayList(feedItems);) inside MyAdapter? or within RSS? Thanks again. – Joe Apr 23 '17 at 22:33
  • @Joe Constructor of your adapter class should be changed, I edited my answer and added the new constructor code – Mahmoud_Mehri Apr 23 '17 at 22:42
  • Thanks! What happens now is that it just doesn't show anything. Like it's not getting any data from xml. Thanks Mahmood! – Joe Apr 23 '17 at 22:51
  • Are you sure you make changes correctly ?, will the list be shown if you use previous adapter's constructor code ?! – Mahmoud_Mehri Apr 23 '17 at 23:01
  • I think so! I've updated my code in my question. No, it seems to never show the rss feeds. Not sure why! It shows it with another link but not this one. Cheers @Mahmood_M – Joe Apr 23 '17 at 23:08
  • Maybe there is another problem in the link address or something else, but the error now goes away by changing the constructor of the adapter and the exception solved – Mahmoud_Mehri Apr 23 '17 at 23:18
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/142426/discussion-between-joe-and-mahmood-m). – Joe Apr 23 '17 at 23:33
0

My best guess is that something is going wrong in your Getdata() function.

This would return null, and that null would be passed silently through several functions creating your null object reference as described.

Trenton Telge
  • 478
  • 3
  • 17
  • Cheers for the answer! I've looked to the best of my knowledge but can't spot anything, I'll keep looking. Thanks – Joe Apr 23 '17 at 22:33