Custom Adapter not showing any data on ListView
Asked Answered
D

4

6

I need a custom adapter for my listView. It needs to be passed to a ASyncTask which will get some data from a RSS feed and then hopefully set that data (at the moment Title and Date, both strings) to the row.

The code I came up with is as follow but it's not doing anything with the adapter.

MainActivity.java

import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;


public class MainActivity extends Activity
{
    private ListView listOne;
    private ListView listTwo;
    RssListViewAdapter adapterOne;
    RssListViewAdapter adapterTwo;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.rss_layout);

        //Connect all three columns to their ListViews
        listOne = (ListView) findViewById(R.id.listOne);
        listTwo = (ListView) findViewById(R.id.listTwo);

        //Create both adapaters
        //TODO: Make custom adapater
        adapterOne = new RssListViewAdapter(this);
        adapterTwo = new RssListViewAdapter(this);


        //Class once for each column. Pass feed URL and Adapter.
        new GetRssFeed("http://feeds.arstechnica.com/arstechnica/index", adapterOne, listOne).execute();
        new GetRssFeed("http://feeds.skynews.com/feeds/rss/home.xml", adapterTwo, listTwo).execute();

    }



}

GetRssFeed.java

import android.os.AsyncTask;
import android.util.Log;
import android.widget.ListView;

/**
 * Created by jameskrawczyk on 07/04/16.
 */
public class GetRssFeed extends AsyncTask<String, Void, Void>
{

    String url;
    RssListViewAdapter adapter;
    ListView listToUse;

    public GetRssFeed(String urlInput, RssListViewAdapter adapterInput, ListView listInput)
    {
        this.url = urlInput;
        this.adapter = adapterInput;
        this.listToUse = listInput;
    }

    @Override
    protected Void doInBackground(String... params)
    {
        try
        {
            RssReader rssReader = new RssReader(url);
            Integer i = 0;

            adapterItem adaptItem = new adapterItem();

            for (RssItem item : rssReader.getItems())
            {
                adaptItem.setHeader(item.getTitle());
                adaptItem.setDate(item.getDate());
                adapter.add(adaptItem);
                i++;
                if(i == 7)
                {
                    break;
                }
            }

        } catch (Exception e)
        {
            Log.v("Error Parsing Data", e + "");
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid)
    {
        super.onPostExecute(aVoid);
        listToUse.setAdapter(adapter);
        adapter.notifyDataSetChanged();

    }
}

RssItem

public class RssItem {
    String title;
    String description;
    String link;
    String imageUrl;
    String pubDate;

    public String getDescription() {
        return description;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }

    public String getTitle() {
        return title;
    }

    public String getLink() {
        return link;
    }

    public String getDate(){return pubDate;}

    public void setLink(String link) {this.link = link;}

    public void setDescription(String description) {
        this.description = description;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setDate(String pubDate) {this.pubDate = pubDate;}
}

RssListViewAdapater

import java.util.ArrayList;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class RssListViewAdapter extends ArrayAdapter<adapterItem> {

    private final Context context;
    private adapterItem itemsArrayList;

    public RssListViewAdapter(Context context) {

        super(context, R.layout.basic_list_item);
        this.context = context;

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {


        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);


        View rowView = inflater.inflate(R.layout.basic_list_item, parent, false);


        TextView headerView = (TextView) rowView.findViewById(R.id.headerName);
        TextView dateView = (TextView) rowView.findViewById(R.id.dateTime);

        headerView.setText(itemsArrayList.getHeader());
        dateView.setText(itemsArrayList.getDate());


        return rowView;
    }

    @Override
    public void add(adapterItem theData)
    {
        this.itemsArrayList = theData;
    }
}

adapterItem

public class adapterItem {

    private String header;
    private String date;

    public adapterItem() {
        super();
        this.header = header;
        this.date = date;
    }


    public void setHeader(String head)
    {
        header = head;
    }

    public void setDate(String dat)
    {
        date = dat;
    }

    public String getHeader()
    {
        return header;
    }

    public String getDate()
    {
        return date;
    }
}
Damalas answered 9/4, 2016 at 4:29 Comment(11)
Where are you adding items to your itemsArrayList?Animadvert
@vrundpurohit In the for loop in GetRssFeed I created a adapterItem and add the data to it then pass it to the adapter with adapter.add(adaptItem) which has had the add function overridden to add the data to itemsArrayListDamalas
you are taking only object of your adapter item. its not arraylist actuallyAnimadvert
@vrundpurohit Ok, but what does that translate to. The whole thing is wrong?Damalas
look for my Answer. NO wait I thought you are using BaseAdapter. sorry.Animadvert
@vrundpurohit I could be using BaseAdapter if that's easier? I was using ArrayAdapter because the example code of the RSS library I'm using did in their example.Damalas
let me prepare for you. wait for my Answer.Animadvert
@JamesKrawczyk may i know Whether RSSReader is Custom Class or any library classLapides
According to the code, only the last added adapterItem can be shown.Commemorative
@Lapides It's this github.com/ShirwaM/Simplistic-RSSDamalas
@JamesKrawczyk i added my answer please check it.Lapides
C
2

In doInBackground of GetRssFeed you instantiate an adapterItem outside for loop, this results in only the last RssItem being added to the adapter. I think you should instantiate every adapterItem inside the for loop.

for (RssItem item : rssReader.getItems())
{
    adapterItem adaptItem = new adapterItem();
    adaptItem.setHeader(item.getTitle());
    adaptItem.setDate(item.getDate());
    adapter.add(adaptItem);
    i++;
    if(i == 7)
    {
       break;
    }
}

Meanwhile it seems you don't override add method of RssListViewAdapater correctly. In fact you don't have to override add at all. The ArrayAdapter will handle it for you.

Commemorative answered 9/4, 2016 at 5:23 Comment(2)
This gave a null reference error on itemsArrayList in RssListViewAdapterDamalas
You can delete the itemsArrayList and in getView use getItem(position) to obtain the rss item.Commemorative
A
2

Use BaseAdapter

public class TestBaseAdap extends BaseAdapter {

ArrayList<adapterItem> itemsArrayList;

public TestBaseAdap(ArrayList<String> itemsArrayList) {
    super();
    this.itemsArrayList = itemsArrayList;
}

@Override
public int getCount() {
    return itemsArrayList.size();
}

@Override
public Object getItem(int position) {
    return position;
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = (LayoutInflater) parent.getContext()
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);


    View rowView = inflater.inflate(R.layout.basic_list_item, parent, false);


    TextView headerView = (TextView) rowView.findViewById(R.id.headerName);
    TextView dateView = (TextView) rowView.findViewById(R.id.dateTime);

    headerView.setText(itemsArrayList.get(position).getHeader());
    dateView.setText(itemsArrayList.get(position).getDate());

    return convertView;
}

}

You just need to take one gobal ArrayList

ArrayList<adapterItem> mArrayList = new ArrayList<adapterItem>();

and then in your asyncTask add like this.

mArrayList.add(adaptItem);

And finally set your adapter like this.

listToUse.setAdapter(new TestBaseAdap(mArrayList));

Done.

Animadvert answered 9/4, 2016 at 4:48 Comment(4)
Where is the ArrayList<adapterItem> mArrayList = new ArrayList<adapterItem>(); going? At the top of GetRssFeed instead of the RssListViewAdapter adapter;Damalas
in your MainActivity. outside onCreateAnimadvert
I've tried that but the AsyncTask class can't see it. Also the RssListViewAdapter is through errors because the constructor contains ArrayList<String>, should that be ArrayList<adapterItem>?Damalas
Ok, so I moved GetRssFeed class into MainActivity as a sub class. Made the changes. Duplicated it as I need to run it for two different ListView's and with mArrayList being hardcoded into the .add function I need a second one with a nArrayList for the second column. However now I get a error with Attempt to invoke virtual method 'int android.view.View.getImportantForAccessibility()' on a null object referenceDamalas
C
2

In doInBackground of GetRssFeed you instantiate an adapterItem outside for loop, this results in only the last RssItem being added to the adapter. I think you should instantiate every adapterItem inside the for loop.

for (RssItem item : rssReader.getItems())
{
    adapterItem adaptItem = new adapterItem();
    adaptItem.setHeader(item.getTitle());
    adaptItem.setDate(item.getDate());
    adapter.add(adaptItem);
    i++;
    if(i == 7)
    {
       break;
    }
}

Meanwhile it seems you don't override add method of RssListViewAdapater correctly. In fact you don't have to override add at all. The ArrayAdapter will handle it for you.

Commemorative answered 9/4, 2016 at 5:23 Comment(2)
This gave a null reference error on itemsArrayList in RssListViewAdapterDamalas
You can delete the itemsArrayList and in getView use getItem(position) to obtain the rss item.Commemorative
L
1

try this one.

Replace

adapter.add(adaptItem);

code as

adapter.addDatas(adaptItem);

in GetRssFeed.java and replace your RssListViewAdapter.java adapter class as

public class RssListViewAdapter extends BaseAdapter {

private final Context context;
private ArrayList<adapterItem> itemsArrayList;


public RssListViewAdapter(Context context) {

    this.context = context;
    itemsArrayList=new ArrayList<adapterItem>();

}

public void addDatas(adapterItem item){
    itemsArrayList.add(item);
}
@Override
public long getItemId(int position) {
    return position;
}

@Override
public Object getItem(int position) {
    return getItem(position);
}

@Override
public int getCount() {
    return itemsArrayList.size();
}




@Override
public View getView(int position, View convertView, ViewGroup parent) {


    LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);


    View rowView = inflater.inflate(R.layout.basic_list_item, parent, false);


    TextView headerView = (TextView) rowView.findViewById(R.id.headerName);
    TextView dateView = (TextView) rowView.findViewById(R.id.dateTime);

    headerView.setText(itemsArrayList.get(position).getHeader());
    dateView.setText(itemsArrayList.get(position).getDate());
    return rowView;
}


}

by Defalut the RssReader doesn't read pubDate from xml.If you wish to read pubDate in RSSReader please copy the code and replace it with RssHandler.java

RssHandler.Java

public class RssHandler extends DefaultHandler {
private List<RssItem> rssItemList;
private RssItem currentItem;
private boolean parsingTitle;
private boolean parsingLink;
private boolean parsingDescription;
private boolean parsingPubDate;
public RssHandler() {
    //Initializes a new ArrayList that will hold all the generated RSS items.
    rssItemList = new ArrayList<RssItem>();
}

public List<RssItem> getRssItemList() {
    return rssItemList;
}


//Called when an opening tag is reached, such as <item> or <title>
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
    if (qName.equals("item"))
        currentItem = new RssItem();
    else if (qName.equals("title"))
        parsingTitle = true;
    else if (qName.equals("link"))
        parsingLink = true;
    else if (qName.equals("description"))
        parsingDescription = true;
    else if(qName.equals("pubDate"))
        parsingPubDate=true;
    else if (qName.equals("media:thumbnail") || qName.equals("media:content") || qName.equals("image")) {
        if (attributes.getValue("url") != null)
            currentItem.setImageUrl(attributes.getValue("url"));

    }
}

//Called when a closing tag is reached, such as </item> or </title>
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
    if (qName.equals("item")) {
        //End of an item so add the currentItem to the list of items.
        rssItemList.add(currentItem);
        currentItem = null;
    } else if (qName.equals("title"))
        parsingTitle = false;
    else if (qName.equals("link"))
        parsingLink = false;
    else if (qName.equals("description"))
        parsingDescription = false;
    else if(qName.equals("pubDate"))
        parsingPubDate=false;
}

//Goes through character by character when parsing whats inside of a tag.
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
    if (currentItem != null) {
        //If parsingTitle is true, then that means we are inside a <title> tag so the text is the title of an item.
        if (parsingTitle)
            currentItem.setTitle(new String(ch, start, length));
            //If parsingLink is true, then that means we are inside a <link> tag so the text is the link of an item.
        else if (parsingLink)
            currentItem.setLink(new String(ch, start, length));
            //If parsingDescription is true, then that means we are inside a <description> tag so the text is the description of an item.
        else if (parsingDescription)
            currentItem.setDescription(new String(ch, start, length));
        else if(parsingPubDate)
            currentItem.setDate(new String(ch,start,length));
    }
}
} 
Lapides answered 9/4, 2016 at 6:52 Comment(2)
I have had just implemented shhp's fix, which worked, but yours looks awesome too. Nice catch on the RssHandler, I had actually already changed that just left it out of my sample code as it wasn't directly relevant to the question.Damalas
Both are valid answers I think but since I already implemented shhp's I haven't had a chance to test yours. I might change the accepted answer to yours if I get a chance to test it.Damalas
A
1

Have same problem. In android 4.1 everything is visible in rows. But in android 6 is empty rows. I fck my mind. But find why.

Just add text color

android:textColor="#000"

Approximation answered 5/9, 2016 at 10:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.