Search code examples
androidxmllistviewlistadapter

Retrieve XML feed,parse it and put it on a listview


I've been coding this script to retrieve XML feed and display it on a webview (with success tutorial url here : http://developer.android.com/training/basics/network-ops/xml.html), however, i am trying to put the entries of the feed on a listview.

public class ListFeed extends ListActivity {
public static final String WIFI = "Wi-Fi";
public static final String ANY = "Any";
private static final String URL = "http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest";

// Whether there is a Wi-Fi connection.
private static boolean wifiConnected = false;
// Whether there is a mobile connection.
private static boolean mobileConnected = false;
// Whether the display should be refreshed.
public static boolean refreshDisplay = true;
public static String sPref = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //setContentView(R.layout.activity_list_feed);

    new DownloadXmlTask().execute(URL);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

private InputStream downloadUrl(String urlString) throws IOException {
    URL url = new URL(urlString);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setReadTimeout(10000 /* milliseconds */);
    conn.setConnectTimeout(15000 /* milliseconds */);
    conn.setRequestMethod("GET");
    conn.setDoInput(true);
    // Starts the query
    conn.connect();
    return conn.getInputStream();
}

   // Uploads XML from stackoverflow.com, parses it, and combines it with
// HTML markup. Returns HTML string.
private List loadXmlFromNetwork(String urlString) throws XmlPullParserException, IOException {
    InputStream stream = null;
    // Instantiate the parser
    StackOverFlowXmlParser stackOverflowXmlParser = new StackOverFlowXmlParser();
    List<StackOverFlowXmlParser.Entry> entries = null;
    String title = null;
    String url = null;
    String summary = null;
    Calendar rightNow = Calendar.getInstance();
    // Checks whether the user set the preference to include summary text
    SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
    boolean pref = sharedPrefs.getBoolean("summaryPref", false);

    // List to store the items
    List<String> feed = new ArrayList<String>();

    try {
        stream = downloadUrl(urlString);
        entries = stackOverflowXmlParser.parse(stream);
        // Makes sure that the InputStream is closed after the app is
        // finished using it.
    } finally {
        if (stream != null) {
            stream.close();
        }
    }
    for (StackOverFlowXmlParser.Entry entry : entries) {
        feed.add(entry.title);
    }

    return feed;
}

    // Implementation of AsyncTask used to download XML feed from stackoverflow.com.
private class DownloadXmlTask extends AsyncTask<String, Void, List> {
    @Override
    protected List doInBackground(String... urls) {
        try {
            return loadXmlFromNetwork(urls[0]);
        } catch (IOException e) {
            //return getResources().getString(R.string.connection_error);
            return null;
        } catch (XmlPullParserException e) {
            //return getResources().getString(R.string.xml_error);
            return null;
        }
    }

    @Override
    protected void onPostExecute(List result) {
        setContentView(R.layout.activity_list_feed);

        //pass the data to the view
        ListView listView = (ListView) findViewById(R.id.list);
        // create adapter to match data to view
        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(ListFeed.this,R.layout.activity_list_feed,result);

        setListAdapter(arrayAdapter);

    }
}

}

Feed fetching is done with AsyncTask,and i want to output in the the listview on the onPostExecute method. I get the "Your content must have a ListView whose id attribute is 'android.R.id.list'" message in the logcat.

here is the XML layout file :

`<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dip"
android:textSize="16dip"
android:textStyle="bold" >
</ListView>`

Note : replacing with TextView leads to the same error thank you for your advice.

Here is the manifest file : `

<uses-permission android:name="android.permission.INTERNET" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
    </activity>
    <activity
        android:name=".WebviewTest"
        android:label="@string/title_activity_webview_test" >
    </activity>
    <activity
        android:name=".SimpleFeed"
        android:label="@string/title_activity_simple_feed" >
    </activity>
    <activity
        android:name=".ListFeed"
        android:label="@string/title_activity_list_feed" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>`

Solution

  • instead of android:id="@+id/list"

    you need android:id="@android:id/list"

    this is an already generated id that the android system can use, rather than one you have created yourself that has the same name.

    Remember all id's in XML are actually represented in Java by an int value. Therefore every time you create a new id a new int will be created. In the above example android:id/list is a known value for the system but you creating id/list is a new number specific to your app and therefore when extending ListActivity (which is system code) the system cannot know and cannot reference your specifical generated id's.