android - WeatherApp, setting an image inside and AsyncTask while parsing XML using setImageResource() -
so i'm working on basic weather application pulls xml yahoo weather api, parses it, , displays information. have async task in doinbackground method pulls xml , uses stringbuilder save xml, , in onpostexecute parses xml in format need. trying set image in mcondimg imageview in post execute, put can't seem working. want have condimg change per codes in xml
public api call: https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3d%22warrensburg%2c%20mo%22)&format=xml&env=store%3a%2f%2fdatatables.org%2falltableswithkeys
weatherfragment.java (the fragment contains of actual parsed axml , asynctask classes.)
import android.app.progressdialog; import android.content.context; import android.net.uri; import android.os.asynctask; import android.os.bundle; import android.os.handler; import android.support.v4.app.fragment; import android.view.layoutinflater; import android.view.view; import android.view.viewgroup; import android.widget.imageview; import android.widget.textview; import org.xmlpull.v1.xmlpullparser; import org.xmlpull.v1.xmlpullparserfactory; import java.io.bufferedreader; import java.io.inputstreamreader; import java.io.stringreader; import java.net.httpurlconnection; import java.net.url; public class weatherfragment extends fragment { static textview mlocation, mcondition, mforecast1, mforecast2, mforecast3, mforecast4, mforecast5; handler handler; imageview mcondimg; private onfragmentinteractionlistener mlistener; public weatherfragment() { handler = new handler(); } public static weatherfragment newinstance(string param1, string param2) { weatherfragment fragment = new weatherfragment(); bundle args = new bundle(); fragment.setarguments(args); return fragment; } @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); } @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { view rootview = inflater.inflate(r.layout.fragment_weather, container, false); mlocation = (textview) rootview.findviewbyid(r.id.location); mcondition = (textview) rootview.findviewbyid(r.id.condition); mforecast1 = (textview) rootview.findviewbyid(r.id.forecast1); mforecast2 = (textview) rootview.findviewbyid(r.id.forecast2); mforecast3 = (textview) rootview.findviewbyid(r.id.forecast3); mforecast4 = (textview) rootview.findviewbyid(r.id.forecast4); mforecast5 = (textview) rootview.findviewbyid(r.id.forecast5); mcondimg = (imageview) rootview.findviewbyid(r.id.condimg); new retrievedata().execute(); return rootview; } // todo: rename method, update argument , hook method ui event public void onbuttonpressed(uri uri) { if (mlistener != null) { mlistener.onfragmentinteraction(uri); } } @override public void ondetach() { super.ondetach(); mlistener = null; } public interface onfragmentinteractionlistener { void onfragmentinteraction(uri uri); } public void changecity(string city){ //updateweatherdata(city); } } class retrievedata extends asynctask<void, void, string> { public static string str; @override protected void onpreexecute() { super.onpreexecute(); } @override protected string doinbackground(void... urls) { try { url url = new url("https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3d%22warrensburg%2c%20mo%22)&format=xml&env=store%3a%2f%2fdatatables.org%2falltableswithkeys"); httpurlconnection urlconnection = (httpurlconnection) url.openconnection(); try { bufferedreader bufferedreader = new bufferedreader(new inputstreamreader(urlconnection.getinputstream())); stringbuilder stringbuilder = new stringbuilder(); string line; while ((line = bufferedreader.readline()) != null) { stringbuilder.append(line).append("\n"); } bufferedreader.close(); str = stringbuilder.tostring(); return stringbuilder.tostring(); } catch (exception e) { e.printstacktrace(); } } catch (exception e) { e.printstacktrace(); } return "error getting weather data"; } protected void onpostexecute(string response) { if (response == null) { response = "error"; } // parse xml try { int forecastcounter = 1; xmlpullparserfactory factory = xmlpullparserfactory.newinstance(); xmlpullparser parser = factory.newpullparser(); parser.setinput(new stringreader(str)); string tagname = null; int event = parser.geteventtype(); while (event != xmlpullparser.end_document) { tagname = parser.getname(); if (event == xmlpullparser.start_tag) { if (tagname.equals("yweather:location")) { weatherfragment.mlocation.settext(parser.getattributevalue(null, "city")); weatherfragment.mlocation.append(", " + parser.getattributevalue(null, "region")); } else if (tagname.equals("yweather:condition")) { weatherfragment.mcondition.settext("current temperature: " + parser.getattributevalue(null, "temp") + "\ncurrent conditions: " + parser.getattributevalue(null, "text")); if (tagname.equals("yweather:code")) { mcondimg.setimageresource(r.drawable.ic_snow); } } else if (tagname.equals("yweather:forecast")) { switch (forecastcounter) { case 1: weatherfragment.mforecast1.settext(parser.getattributevalue(null, "day") + " - high: " + parser.getattributevalue(null, "high") + " - low: " + parser.getattributevalue(null, "low") + " - " + parser.getattributevalue(null, "text")); forecastcounter++; if (weatherfragment.mcondition.gettext().equals("28")) { //weatherfragment.mcondimg.setimageresource(r.drawable.ic_sunny);//this works } break; case 2: weatherfragment.mforecast2.settext(parser.getattributevalue(null, "day") + " - high: " + parser.getattributevalue(null, "high") + " - low: " + parser.getattributevalue(null, "low") + " - " + parser.getattributevalue(null, "text")); forecastcounter++; break; case 3: weatherfragment.mforecast3.settext(parser.getattributevalue(null, "day") + " - high: " + parser.getattributevalue(null, "high") + " - low: " + parser.getattributevalue(null, "low") + " - " + parser.getattributevalue(null, "text")); forecastcounter++; break; case 4: weatherfragment.mforecast4.settext(parser.getattributevalue(null, "day") + " - high: " + parser.getattributevalue(null, "high") + " - low: " + parser.getattributevalue(null, "low") + " - " + parser.getattributevalue(null, "text")); forecastcounter++; break; case 5: weatherfragment.mforecast5.settext(parser.getattributevalue(null, "day") + " - high: " + parser.getattributevalue(null, "high") + " - low: " + parser.getattributevalue(null, "low") + " - " + parser.getattributevalue(null, "text")); forecastcounter++; break; } } } event = parser.next(); } } catch (exception e) { e.printstacktrace(); } //mweatherdata.settext(str); } }
weatherfragment.xml (used styling fragment)
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" > <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margintop="-140sp" android:textsize="30sp" android:id="@+id/location"/> <imageview android:layout_width="300px" android:layout_height="300px" android:src="@drawable/ic_sunny" android:id="@+id/condimg" /> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="left" android:layout_marginleft="15sp" android:layout_marginbottom="7sp" android:id="@+id/condition"/> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginbottom="10sp" android:textsize="20sp" android:text="@string/multiforecast" /> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="left" android:layout_marginleft="15sp" android:layout_marginbottom="7sp" android:id="@+id/forecast1" /> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="left" android:layout_marginleft="15sp" android:layout_marginbottom="7sp" android:id="@+id/forecast2" /> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="left" android:layout_marginleft="15sp" android:layout_marginbottom="7sp" android:id="@+id/forecast3" /> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="left" android:layout_marginleft="15sp" android:layout_marginbottom="7sp" android:id="@+id/forecast4" /> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="left" android:layout_marginleft="15sp" android:layout_marginbottom="7sp" android:id="@+id/forecast5" /> <!--<scrollview android:layout_width="match_parent" android:layout_height="match_parent"> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/weather_data" /> </scrollview>--> </linearlayout>
the problem adding namespaces tag names in code. example, given tag:
<yweather:condition xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" code="29" date="sun, 24 apr 2016 09:00 pm cdt" temp="68" text="partly cloudy" />
the tag name "condition"
, not "yweather:condition"
. namespace "yweather"
. check proper tag should this:
if ("condition".equals(tagname))
if want check namespace matches, can this:
if ("condition".equals(tagname) && "yweather".equals(parser.getnamespace())
it's worth mentioning code doing xml parsing on main (ui) thread because doing inside of onpostexecute()
. should doing parsing inside of doinbackground()
instead; onpostexecute()
should reserved smallest amount of code modifies ui.
you can take advantage of fact asynctask
parameterized , have doinbackground()
return class define hold results of parsing, so:
private static class weatherresults { private int conditionimage; private string condition; private string location; ... } class retrievedata extends asynctask<void, void, weatherresults> { @override protected string doinbackground(void... params) { weatherresults weatherresults = new weatherresults(); // make web call // parse xml , set results, e.g. // weatherresults.conditionimage = r.drawable.ic_snow; return weatherresults; // can return null instead if there's error } @override protected void onpostexecute(weatherresults result) { if (result == null) { // show error state return; } // update ui mcondimg.setimageresource(result.conditionimage); // etc. } }
Comments
Post a Comment