Search code examples
androidlistviewarraylistnullpointerexceptionlistadapter

Android, Null Pointer Exception on ListView test code


I am building an app that uses ListView and a custom adapter extending BaseAdapter to handle the data to the ListView. The code is as follows:

newlist.java compiles/runs fine

public class newslist extends Activity {

    public static final String tag = "newslist";
    ListView listNews;
    MyListAdapter listAdapter;


    /** Set or Grab the URL */        
    public static final String parseURL = "http://www.example.com.gr/article.php";

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.newslist);

        /** Array Lists */
        ArrayList<String> titles = new ArrayList<String>();
        ArrayList<String> links = new ArrayList<String>();
        ArrayList<String> dates = new ArrayList<String>();

        Log.d(newslist.tag, "****** parseURL = " + parseURL);

        listNews = (ListView) findViewById(R.id.listNews);

        try {                  
            /** Open URL with Jsoup */
            Document doc = Jsoup.connect(parseURL).get();

            /** Grab classes we want */                   
            Elements pcontent = doc.getElementsByClass("content_title");
            Elements pdates = doc.getElementsByClass("content_datecreated_left");

            /** Loop for grabbing TITLES within parent element */
            for (Element ptitles : pcontent) {

                /** Grab Anchors */
                Elements ptitle = ptitles.getElementsByTag("a");
                for (Element title : ptitle) {
                  titles.add(title.text());
                }
            }

            /** Loop for grabbing LINKS within parent element */
            for (Element plinks : pcontent) {
                /** Grab anchors */
                Elements plink = plinks.getElementsByTag("a");
                for (Element link : plink) {                    
                  links.add(link.attr("abs:href")); /** parse absolute address */    
                }
            }

            /** Loop for grabbing DATES within parent element */
            for (Element pdate : pdates) {
                dates.add(pdate.text()) ;
            }

            //TODO: Regex on Date

            //String content: Main Activity Content

            int i=0;
            int num = titles.size();
            String[] printDates = new String[num];
            for (i=0; i < num; i++)
            {
                //substring(25) leaves a space after the date, eg "26/6/2011 "
                //content[i] = titles.get(i) + "\n Date: " + dates.get(i).substring(25);
                printDates[i] = dates.get(i).substring(25);
            }

            /** Create an ArrayAdapter, that will actually make the Strings above 
             * appear in the ListView */ 
            listAdapter = new MyListAdapter(this, titles, dates);
            listNews.setAdapter(listAdapter);

        } catch (Exception e) {
            Log.e(newslist.tag, "****** Failed to Parse URL:" + e.getMessage());
            e.printStackTrace();
        } 

    } /*- OnCreate End -*/

} /*- Class End -*/

MyListAdapter.java runs a NPE at line 75:

public class MyListAdapter extends BaseAdapter {

    public final static String tag = "MyListAdapter";
    public Context context;
    public ArrayList<String> title;
    public ArrayList<String> date;
    public LayoutInflater inflater;

    public MyListAdapter(Activity context, ArrayList<String> title, ArrayList<String> date) {
        super();
        this.context = context;
        this.title = title;
        this.date = date;

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

    public int getCount() {
        // Auto-generated method stub
        return this.title.size();
    }

    public Object getItem(int position) {
        //Auto-generated method stub
        return this.title.get(position);
    }

    public long getItemId(int position) {
        // Auto-generated method stub
        return position;
    }

    private static class ViewHolder {
        TextView titleView;
        TextView dateView;
    }

    public View getView(int position, View convertView, ViewGroup parent)
    {
        // Auto-generated method stub
        ViewHolder holder;

        Log.d(tag, "****** convertView: " + convertView);

        if (convertView == null)
        {
            convertView = inflater.inflate(R.layout.listrow, null);
            holder = new ViewHolder();
            holder.titleView = (TextView) convertView.findViewById(R.id.listTitle);
            holder.dateView = (TextView) convertView.findViewById(R.id.listDate);
            convertView.setTag(holder);
        }
        else
        {
            holder = (ViewHolder) convertView.getTag();
        }
        Log.d(tag, "****** Title: " + title.get(position));
        Log.d(tag, "****** findViewById: " + convertView.findViewById(R.id.listTitle));
        Log.d(tag, "****** holder.titleView: " + holder.titleView);


        holder.titleView.setText(title.get(position));
        holder.dateView.setText(date.get(position));

        //notifyDataSetChanged();

        return convertView;
    }

}

Line 75 is:

holder.titleView.setText(title.get(position));

However I have tracked the problem to line 62:

holder.titleView = (TextView) convertView.findViewById(R.id.listTitle);

where it seems from my debugging messages that holder.titleView is null

I have tried cleaning/erasing bin folder and rebuilding the project to no avail. I think the problem lies in the View R.id.listTitle not being found. But i have no idea why.

I will also include my two xml files for previewing

newslist.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >
<TextView  
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:id="@+id/title"
    android:gravity="center|top"
    android:textSize="20dip"
    android:textStyle="bold"
    android:text="@string/titleNewslist"
    />
<ListView  
    android:id="@+id/listNews"
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"
    >
</ListView>
</LinearLayout>

listrow.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:name="@+id/listTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="top|left"
        android:textSize="18dip"
        android:textStyle="bold"
        android:text="TextView">
    </TextView>  
    <TextView
        android:name="@+id/listDate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="bottom|right"
        android:textSize="12dip"
        android:textStyle="bold"
        android:textColor="@android:color/white"
        android:text="TextView">
    </TextView>
</LinearLayout>

Solution

  • You never assign anything to titleView.

    You need to do the following in your onCreate() after super.onCreate()

    titleView = (TextView) this.getViewById(R.id.listTitle);
    

    Make sure to declare titleView as a field at the top of your class so the rest of your class can access it, if you need to.

    Hope this helps!

    EDIT:

    An important note I just noticed:

    android:name="@+id/myName" 
    

    is NOT the same as

    android:id="@+id/myName"
    

    You need to make sure you declare the ids, or you will not be able to access the layout elements.