1

In my Fragment I'm displaying the RSS feed from a news page on the Web, but I'm able to get these datas only from one Url. Then I display the data of this single Url in my Custom Listview. So, Is there a way I can show datas from more than one Url displayed in different Listviews but in the same Fragment? Perhaps what I am asking is not clear,if so comment and check the image I made below:

enter image description here

Here there's the code that I have in my Fragment:

try {
        URL rssUrl = new URL("URL1");
        SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();
        SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
        XMLReader myXMLReader = mySAXParser.getXMLReader();
        RSSHandler myRSSHandler = new RSSHandler();
        myXMLReader.setContentHandler(myRSSHandler);
        InputSource myInputSource = new InputSource(rssUrl.openStream());
        myXMLReader.parse(myInputSource);

        myRssFeed = myRSSHandler.getFeed();

    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ParserConfigurationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (SAXException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }


    if (myRssFeed!=null)
    {
        ListView list = (ListView)view.findViewById(android.R.id.list);
        CustomList adapter = new CustomList(getActivity(),myRssFeed.getList());
        adapter.addAll();
        list.setAdapter(adapter);

    }
    else
        Toast.makeText(getActivity(), "....",
                Toast.LENGTH_LONG).show();
    return view;
}

Edit Custom ListView for a Url:

public class CustomList extends ArrayAdapter<RSSItem> {

private static Activity context = null;
private final List<RSSItem> web;
private SharedPreferences mPrefs;
final String read2 = "text1";
final String testoread2 = "img1";

public CustomList(Activity context, List<RSSItem> web) {
    super(context, R.layout.custom_list, web);
    CustomList.context = context;
    this.web = web;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
    LayoutInflater inflater = context.getLayoutInflater();
    final View rowView = inflater.inflate(R.layout.custom_list, null, true);
    mPrefs = PreferenceManager.getDefaultSharedPreferences(context);

    if (android.os.Build.VERSION.SDK_INT > 9) {
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
    }

    ....


    return rowView;

}

Any suggestion is appreciated.

EDIT2 What I have now:

try {
        URL rssUrl = new URL("URL1");
        URL rssUrl2 = new URL("URL2");
        SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();

        SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
        SAXParser mySAXParser2 = mySAXParserFactory.newSAXParser();

        XMLReader myXMLReader = mySAXParser.getXMLReader();
        XMLReader myXMLReader2 = mySAXParser2.getXMLReader();

        RSSHandler myRSSHandler = new RSSHandler();
        RSSHandler2 myRSSHandler2 = new RSSHandler2();

        myXMLReader.setContentHandler(myRSSHandler);
        myXMLReader2.setContentHandler(myRSSHandler2);

        InputSource myInputSource = new InputSource(rssUrl.openStream());
        InputSource myInputSource2 = new InputSource(rssUrl2.openStream());

        myXMLReader.parse(myInputSource);
        myXMLReader2.parse(myInputSource2);

        myRssFeed = myRSSHandler.getFeed();
        myRssFeed2 = myRSSHandler2.getFeed();
Rick
  • 3,943
  • 6
  • 33
  • 45
  • inside the fragment, don't push a ListView. instead, push a **vertical linear layout** with layout_height=wrap_content. each row in this LinearLayout will place a ListView. you can achive this dynamiclly by using: myLinearLayout.addView(childListView); – ymz Nov 25 '14 at 21:29
  • May you give me an example? – Rick Nov 25 '14 at 21:33
  • posted it now.. please check if it suits you – ymz Nov 25 '14 at 22:04

3 Answers3

1

instead of placing your ListView in the xml, load it dynamically:

ListView list = new ListView(this);
CustomList adapter = new CustomList(getActivity(),myRssFeed.getList());
adapter.addAll();
list.setAdapter(adapter);

then in your xml place a LinearLayout with these attributes:

android:id="@+id/layoutMain"
android:orientation="vertical"
android:layout_height="wrap_content"

back to Java - add your list view to the LinearLayout:

LinearLayout layoutMain = (LinearLayout)findViewById(R.id.layoutMain);
layoutMain.addView(list);

repeat this step for a couple of times to populate your Fragment with multiple lists

EDIT:

about the RssHandlers - please create a function to handle those:

RSSHandler createRssHandler(SAXParserFactory mySAXParserFactory, String url)
{
    URL rssUrl = new URL(url);
    SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
    XMLReader myXMLReader = mySAXParser.getXMLReader();
    RSSHandler myRSSHandler = new RSSHandler();
    myXMLReader.setContentHandler(myRSSHandler);
    InputSource myInputSource = new InputSource(rssUrl.openStream());
    myXMLReader.parse(myInputSource);

   return myRSSHandler;
}

now you can use it with array:

String[] urls = new String["url1", "url2"];
RssHandlers[] handlers = new RssHandlers[urls.length];

for (int i = 0; i < urls.length; i++)
{
     handlers[i] = createRssHandler(mySAXParserFactory, urls[i]); 
} 

combine it with your lists will result something like that:

String[] urls = new String["url1", "url2"];
RssHandlers[] handlers = new RssHandlers[urls.length];
LinearLayout layoutMain = (LinearLayout)findViewById(R.id.layoutMain);

for (int i = 0; i < urls.length; i++)
{
     handlers[i] = createRssHandler(mySAXParserFactory, urls[i]); 

     ListView list = new ListView(this);
     CustomList adapter = new CustomList(getActivity(), handlers[i].getList());
     adapter.addAll();
     list.setAdapter(adapter);
     layoutMain.addView(list);
} 
ymz
  • 6,602
  • 1
  • 20
  • 39
  • And then what should I do to assing different Urls to each Listview? – Rick Nov 25 '14 at 22:07
  • each list view is bound to a list - in your code myRssFeed.getList(). you need to populate several lists, each from a different url. every ListView will then be bound to a different list with multiple items represented by a specific url – ymz Nov 25 '14 at 22:10
  • Okay I'll work on it and I'll let you know. Thanks for your help :D – Rick Nov 25 '14 at 22:17
  • I voted your answer but I encountered a problem: when I put the other Url (so now I should get the feed of two Urls) and run my project, It is displayed only the Urls I added. Check the edit to see what I've done – Rick Nov 25 '14 at 22:52
  • I mean: _layoutMain.addView(list); layoutMain.addView(list2); //It is only shown the datas of the Url of list2_ – Rick Nov 25 '14 at 23:29
  • So the code you wrote for RSSHandler can read the datas from different Urls even if they're called differently? – Rick Nov 26 '14 at 15:54
  • yes...each handler is unique for a specific url and a targeted ListView.. please try it ann post back – ymz Nov 26 '14 at 15:56
  • Sorry to bother you again but I can't get where I have to put the RSSHandler stuff. Inside: _try { ... }_ ? – Rick Nov 26 '14 at 16:13
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/65721/discussion-between-ymz-and-riccardo-fabozzi). – ymz Nov 26 '14 at 20:54
  • Check the chat, today the bounty ends ;) – Rick Dec 01 '14 at 12:49
0

First, I'm a bit confused about your goal. Do you mean that you are hoping to have separate ListViews in the same Fragment, where each ListView is showing items from a different URL? If that is your goal, then you should not do that. It really doesn't work well at all to have multiple ListViews in a scrolling list.

What you can do, however, is build an adapter that handles multiple URLs, and have a single ListView (maybe that is already your goal). In the adapter constructor, you would build a combined list of all the feed items that you find in all the URLs. Your adapter would look like this:

public class CustomList extends BaseAdapter {

    private final List<FeedItem> itemList;

    public CustomList(List<URL> urlList) {
        itemList = new ArrayList<FeedItem>();
        for (URL rssUrl: urlList) {
            //TODO your code to extract feed items from a URL
            itemList.addAll(myRssFeed.getList());
        }
    }

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

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            //TODO inflate your view from XML
        }
        FeedItem feedItem = itemList.get(position);
        //TODO configure convertView using the data in feedItem
        return convertView;
    }
}
Bruce
  • 2,377
  • 1
  • 17
  • 11
  • Sorry I'm a bit confused at the moment, I already have a Custom ListView. Check the edits – Rick Nov 23 '14 at 02:44
  • Yes I know, I was trying to suggest a change to your adapter. Are you giving your adapter the list items from ONE URL? If so my suggestion is to have your adapter manage ALL URLs. But maybe I misunderstood. Maybe you already are using one adapter, have only one ListView in your Fragment, and are asking how to configure each item from different feeds? The answer to that is that you have to get the data for each feed item (in getView), and modify your views accordingly. Does that make sense? Sorry if I'm misunderstanding your problem. – Bruce Nov 23 '14 at 02:55
  • Yes I am trying to configure each item from different feeds. Don't worry for the misunderstanding, I don't have much "language skills" so It's not all your fault. Anyway thanks for your attention :) – Rick Nov 23 '14 at 03:01
  • Sure, no problem. It sounds like your issue is that you need to take different types of content, and squeeze it into the same view? Or maybe the content is too different, and you really need different view layouts? Is that right? If so you can use getItemViewType to define different view types depending on which URL they came from. Then you can inflate different view layouts in getView. Let me know if you need more detail about that. – Bruce Nov 23 '14 at 03:13
  • It's not that the content is too different, the items i take from the URL are just called different. For example the images in a URL is called _enclosure_ and in another URL is called _thumbimage_ – Rick Nov 23 '14 at 11:42
0

This is how i would do this:

  1. Upon starting this fragment, start some sort of a loading animation.
  2. Spawn a separate thread (or Loader) for each URL you are hitting (within reason, schedule further as needed) and keep track of which Loaders finished. Once all loaders finish, concatenate the articles they return into some list of objects. Since each URL returns a different object, create a unified model that is aware of the URL where article came from (or type of the article) and is able to standardize data into the same List object. Later on, when you are loading a view for it, you can customize it based on, say, the URL it came from.
  3. Once all loaders finished loading, stop loading animations and use the resulting list of objects to populate your list view.

You should user Loaders with LoaderManager for this. Here is a good tutorial.

C0D3LIC1OU5
  • 8,600
  • 2
  • 37
  • 47
  • Is there an easier way to do this without Loading Animations? I just want that for a Url I have a ListView and another Listviews for other Urls – Rick Nov 24 '14 at 21:56
  • you don't have to use animations, its just that you definitely need to perform all network interaction on a separate thread. And the user needs to know that something is happening - so using a loading amination while you are loading something from the internet is pretty much they way do go. – C0D3LIC1OU5 Nov 24 '14 at 21:58
  • Also, you are doing networking stuff on the UI thread. that's a big no no. Here is more info: http://stackoverflow.com/questions/6343166/android-os-networkonmainthreadexception – C0D3LIC1OU5 Nov 24 '14 at 22:02
  • Sorry when I copied the code from my project I forgot this: _if (android.os.Build.VERSION.SDK_INT > 9) { StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); }_ – Rick Nov 24 '14 at 22:16
  • Code above disables throwing an exception when system detects activity like network access from the UI thread. Suppressing that exception doesn't change the fact that you are not supposed to do this, here is an official explanation: http://developer.android.com/training/basics/network-ops/connecting.html#AsyncTask – C0D3LIC1OU5 Nov 24 '14 at 22:35
  • So the only way to have different ListViews in one Fragment is the one you said? I hoped that this thing was easy to do – Rick Nov 24 '14 at 22:40
  • I wouldn't say that's the only way, it is the way I would personally do this. Your task seems fairly complex and the approach I suggest would be the cleanest given that you have a sensible number of URL's you are fetching from imho. If you have more then 3 URL's, I think further request scheduling would be needed... – C0D3LIC1OU5 Nov 24 '14 at 22:46
  • I'll comment tomorrow to let you know. I'm pretty stuck on this thing and i knew it was difficoult to sort out. I hope this doesn't take too much time... – Rick Nov 24 '14 at 23:08