Deze app zou RSS-feeds ophalen van een enkel, door de gebruiker gespecificeerd internetadres, en de inhoud weergeven met een recyclerview. Als u niet bekend bent met de RecyclerView-widget, bekijk dan onze vorige tutorial over het gebruik van een RecyclerView.
RSS, of Rich Site Summary, is een eenvoudige en efficiënte manier om fragmenten van regelmatig bijgewerkte informatie te delen als blogberichten of nieuwsitems met abonnees. Bijna elke nieuwswebsite heeft vandaag een RSS-feed die toegankelijk is via uw favoriete browser. Naar RSS-feed bevat meestal een samenvatting van de nieuwe inhoud, in plaats van het hele nieuws (of blog) artikel. Om je vraag te beantwoorden, ja, Android Authority heeft een RSS-feed, beschikbaar op //feed.androidauthority.com/, en je moet je abonneren als je dat nog niet hebt gedaan. : D
Voorbeeld RSS-feed
Een RSS-feed is een eenvoudig tekstdocument, geformatteerd in XML. Omdat het XML is, is het relatief eenvoudig voor mensen om te lezen, en daarom is het niet moeilijk om programma's te ontleden. Een voorbeeld van een XML-document wordt hieronder getoond.
RSS Titel Dit is een voorbeeld van een RSS-feed //www.example.com/main.html Maa, 06 Sep 2010 00:01:00 +0000 zo, 06 Sep 2009 16:20:00 +0000 1800 Voorbeeld invoer Hier is een tekst met een interessante beschrijving. //www.example.com/blog/post/1 7bd204c6-1655-4c27-aeee-53f933c5395f Zo, 06 Sep 2009 16:20:00 +0000 Tweede voorbeeld entry Meer tekst met een nog interessantere beschrijving. //www.example.com/blog/post/2 7a4a56b6-1655-4c27-aeee-33e4453f2675 zo, 06 sep 2009 18:14:00 +0000
We kunnen aan de hand van het bovenstaande voorbeeld zien dat de feed een titel, een beschrijving, een link, de laatste builddatum, een publicatiedatum en een tijd om te leven heeft. Voor deze zelfstudie zijn we alleen geïnteresseerd in de titel, beschrijving en link.
Er zijn dus twee items in de feed en elk heeft een titel, een beschrijving en een koppeling, samen met een guid (globaal unieke ID) en publicatiedatum. RSS-feed, we zijn alleen bezig met de titel, beschrijving en link.
Het project voorbereiden
Natuurlijk, het eerste wat we doen is een nieuw Android Studio-project maken met een lege activiteit, die we zojuist SimpleRSSReader hebben genoemd. In het bestand AndroidManifiest.xml nemen we de INTERNET-machtiging op. Omdat de RSS-lezer van internet wil eten, moeten we deze toestemming geven.
Daarom zijn we van plan de ondersteuningsbibliotheek, RecyclerView en ontwerp-ondersteuningsbibliotheek te gebruiken, dus we voegen deze toe aan ons app-bestand build.gradle. De nieuwste versie bij publicatie is 25.0.1.
compileer 'com.android.support:appcompat-v7:25.0.1' compileer 'com.android.support:recyclerview-v7:25.0.1' compile 'com.android.support:design:25.0.1'
Grote. Als de eerste installatie is voltooid, gaan we aan de slag.
Ontwerp de lay-out
Onze rss-readerapp wil de feed ophalen en de feeditems weergeven in een recycliewiew.
Is het u opgevallen dat we ons recyclerview hebben opgenomen in een SwipeRefreshLayout? Een SwipeRefreshLayout is een bibliotheek voor ontwerpondersteuning.
De hoofdactiviteit maken
Binnen de klasse MainActivity bepalen we eerst de EditText, de Button, RecyclerView en SwipeLayout. Daarom hebben we een kliklistener ingesteld voor de knop en op OnRefreshListener voor de SwipeRefreshLayout.
public class MainActivity breidt AppCompatActivity uit {private RecyclerView mRecyclerView; privé EditText mEditText; privéknop mFetchFeedButton; Private SwipeRefreshLayout mSwipeLayout; private TextView mFeedTitleTextView; privé TextView mFeedLinkTextView; private TextView mFeedDescriptionTextView; privélijst mFeedModelList; privé string mFeedTitle; privé string mFeedLink; private string mFeedDescription; @Override protected void onCreate (bundle savedInstanceState) {super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); mRecyclerView = (RecyclerView) findViewById (R.id.recyclerView); mEditText = (EditText) findViewById (R.id.rssFeedEditText); mFetchFeedButton = (knop) findViewById (R.id.fetchFeedButton); mSwipeLayout = (SwipeRefreshLayout) findViewById (R.id.swipeRefreshLayout); mFeedTitleTextView = (TextView) findViewById (R.id.feedTitle); mFeedDescriptionTextView = (TextView) findViewById (R.id.feedDescription); mFeedLinkTextView = (TextView) findViewById (R.id.feedLink); mRecyclerView.setLayoutManager (nieuwe LinearLayoutManager (this)); mFetchFeedButton.setOnClickListener (nieuwe View.OnClickListener () {@Override public void onClick (View view) {nieuwe FetchFeedTask (). execute ((Void) null);}}); mSwipeLayout.setOnRefreshListener (new SwipeRefreshLayout.OnRefreshListener () {@Override public void onRefresh () {new FetchFeedTask (). execute ((void) null);}}); }}
Zowel de Button als SwipeRefreshLayout voeren dezelfde actie uit, namelijk het starten van een nieuw FetchFeedTask. Het FetchFeedTask bevindt zich op AsyncTask, waarmee we langlopende taken in een achtergrondthread kunnen uitvoeren. Als u feeds van een bron op de hoofdthread probeert op te halen, reageert uw app niet meer en werkt u mogelijk niet meer. Sinds Ice-cream Sandwich staat Android niet langer toe dat apps netwerkoproepen plaatsen op de rode draad. Voor een herhaling van het gebruik van AsyncTask, kunt u ons vorige artikel over het gebruik van een web-API uit uw Android-app bekijken.
Het FetchFeedTask heeft drie eenvoudige methoden:
- onPreExecute, dat wordt aangeroepen voordat de lange taak wordt gestart, en wordt uitgevoerd op de aanroepende thread.
- doInBackground, wat de langlopende taak is, en wordt uitgevoerd in een nieuwe thread
- onPostExecute, dat wordt uitgevoerd op de aanroepende thread.
Omdat Android manipulatie van UI-elementen (Buttons, SwipeRefreshLayout, enz.) Alleen op de UI / Main thread toestaat, kunnen we de UI zowel onPreExecute, als onPostExecute, maar niet in doInBackground updaten.
private class FetchFeedTask breidt AsyncTask uit {private string urlLink; @Override beschermde leegte onPreExecute () {mSwipeLayout.setRefreshing (true); urlLink = mEditText.getText (). toString (); } @Override beschermd Boolean doInBackground (void ... voids) {if (TextUtils.isEmpty (urlLink)) return false; probeer {if (! urlLink.startsWith ("//") &&! urlLink.startsWith ("//")) urlLink = "//" + urlLink; URL url = nieuwe URL (urlLink); InputStream inputStream = url.openConnection (). GetInputStream (); mFeedModelList = parseFeed (inputStream); keer terug waar; } catch (IOException e) {Log.e (TAG, "Error", e); } catch (XmlPullParserException e) {Log.e (TAG, "Error", e); } return false; } @Override beschermde ongeldig op PostExecute (Booleaans succes) {mSwipeLayout.setRefreshing (false); if (succes) {mFeedTitleTextView.setText ("Feed Title:" + mFeedTitle); mFeedDescriptionTextView.setText ("Feedbeschrijving:" + mFeedDescription); mFeedLinkTextView.setText ("Feedlink:" + mFeedLink); // Fill RecyclerView mRecyclerView.setAdapter (nieuwe RssFeedListAdapter (mFeedModelList)); } else {Toast.makeText (MainActivity.this, "Voer een geldige RSS-feed url in", Toast.LENGTH_LONG) .show (); }}}
In het bovenstaande codefragment ziet u alleen de UI in onPreExecute en onPostExecute, terwijl alle berekeningen binnen doInBackground worden uitgevoerd. We definiëren FetchFeedTask als een binnenklasse in MainActivity, zodat we toegang hebben tot de MainActivity-layoutwidgets.
In doInBackground bevestigen we eerst dat de ingevoerde URL niet leeg is. Vervolgens voegen we een '//' toe aan de URL als de gebruiker deze heeft weggelaten. De volgende stap is om een url-verbinding te openen met behulp van de methode url.getConnection (). GetInputStream (). Ten slotte noemen we een methode met de naam parsefeed () om de resulterende RSS-feed te ontleden.
De RSS-feed parseren
Gelukkig bevat Android enkele hulpprogramma's en interfaces om XML-ontleding te verwerken. Voor onze rss-lezer willen we het XmlPullParser-exemplaar gebruiken om de feed te parseren. XmlPullParser heeft mogelijk een InputStream of een Reader als de bron van gegevens. We lezen zojuist elke XML-tag in de RSS-feed totdat we aan het einde van het document komen. Je kunt het in het onderstaande XML-fragment zien, het is een titel, beschrijving of link.
public List parseFeed (InputStream inputStream) gooit XmlPullParserException, IOException {String title = null; Stringlink = null; Stringbeschrijving = null; boolean isItem = false; Lijstitems = nieuwe ArrayList (); probeer {XmlPullParser xmlPullParser = Xml.newPullParser (); xmlPullParser.setFeature (XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); xmlPullParser.setInput (inputStream, null); xmlPullParser.nextTag (); while (xmlPullParser.next ()! = XmlPullParser.END_DOCUMENT) {int eventType = xmlPullParser.getEventType (); Stringnaam = xmlPullParser.getName (); als (naam == null) doorgaan; if (eventType == XmlPullParser.END_TAG) {if (name.equalsIgnoreCase ("item")) {isItem = false; } ga verder; } if (eventType == XmlPullParser.START_TAG) {if (naam.equalsIgnoreCase ("item")) {isItem = true; voort te zetten; }} Log.d ("MyXmlParser", "Parsing name ==>" + name); Stringresultaat = ""; if (xmlPullParser.next () == XmlPullParser.TEXT) {result = xmlPullParser.getText (); xmlPullParser.nextTag (); } if (name.equalsIgnoreCase ("title")) {title = result; } else if (name.equalsIgnoreCase ("link")) {link = resultaat; } else if (name.equalsIgnoreCase ("description")) {description = result; } if (title! = null && link! = null && description! = null) {if (isItem) {RssFeedModel item = new RssFeedModel (titel, link, beschrijving); Items.Add (item); } else {mFeedTitle = titel; mFeedLink = link; mFeedDescription = beschrijving; } title = null; link = nul; beschrijving = null; isItem = false; }} items retourneren; } eindelijk {inputStream.close (); }}
RssFeedModel is een eenvoudige helperklasse.
public class RssFeedModel {public String title; openbare stringlink; openbare stringbeschrijving; public RssFeedModel (String title, String link, String description) {this.title = title; this.link = link; this.description = beschrijving; }}
De feeds weergeven
Op dit moment zijn we klaar om RSS-feeds te downloaden en te analyseren. We moeten de resultaten echter nog steeds weergeven in onze RSS-lezer RecyclerView. Onthoud dat in de methode onPostExecute () hierboven de regel staat:
mRecyclerView.setAdapter (nieuwe RssFeedListAdapter (mFeedModelList));
Nogmaals, als u nog niet eerder een RecyclerView hebt gebruikt, bekijk dan onze vorige tutorial over het gebruik van RecyclerView. Het is heel gemakkelijk en eenvoudig te gebruiken. Een lay-outbestand maken met de naam item_rss_feed.xml.
En tot slot, de RssFeedListAdapter.
public class RssFeedListAdapter breidt RecyclerView.Adapter {private List mRssFeedModels; public static class FeedModelViewHolder breidt RecyclerView.ViewHolder uit {private view rssFeedView; openbare FeedModelViewHolder (View v) {super (v); rssFeedView = v; }} public RssFeedListAdapter (Lijst rssFeedModels) {mRssFeedModels = rssFeedModels; } @Override openbaar FeedModelViewHolder onCreateViewHolder (ViewGroup-bovenliggend, int-type) {View v = LayoutInflater.from (parent.getContext ()) .inflate (R.layout.item_rss_feed, parent, false); FeedModelViewHolder-houder = nieuwe FeedModelViewHolder (v); terugkeer houder; } @Override public void onBindViewHolder (FeedModelViewHolder-houder, int-positie) {final RssFeedModel rssFeedModel = mRssFeedModels.get (positie); . ((Text View) holder.rssFeedView.findViewById (R.id.titleText)) setText (rssFeedModel.title); ((TextView) holder.rssFeedView.findViewById (R.id.descriptionText)) .setText (rssFeedModel.description); ((Text View) holder.rssFeedView.findViewById (R.id.linkText)) setText (rssFeedModel.link). } @Override public int getItemCount () {return mRssFeedModels.size (); }}
Afronden
Zoals altijd is de volledige bron beschikbaar op github. Je kunt kijken hoe je item_rss_feed.xml stileert en meer inhoud weergeeft dan alleen de titel, beschrijving en link, en / of voor de avontuurlijke, het schrijven van je eigen RSS-nieuwsaggreagator met meerdere feeds uit meerdere bronnen.
Happy codering.