java - Android NullPointerException in ArrayAdapter<String> due to AsyncTask onPostExecute() -
i'm having trouble null pointer exception on android project when using asynctask. exception follows:
03-17 02:17:36.774 14084-14084/me.ashkelon.sunshine w/dalvikvm﹕ threadid=1: thread exiting uncaught exception (group=0x41934ce0) 03-17 02:17:36.784 14084-14084/me.ashkelon.sunshine e/androidruntime﹕ fatal exception: main process: me.ashkelon.sunshine, pid: 14084 java.lang.nullpointerexception @ android.widget.arrayadapter.createviewfromresource(arrayadapter.java:394) @ android.widget.arrayadapter.getview(arrayadapter.java:362) @ android.widget.abslistview.obtainview(abslistview.java:2255) @ android.widget.listview.makeandaddview(listview.java:1790) @ android.widget.listview.filldown(listview.java:691) @ android.widget.listview.fillspecific(listview.java:1349) @ android.widget.listview.layoutchildren(listview.java:1608) @ android.widget.abslistview.onlayout(abslistview.java:2087) @ android.view.view.layout(view.java:14841) @ android.view.viewgroup.layout(viewgroup.java:4631) @ android.widget.framelayout.layoutchildren(framelayout.java:453) @ android.widget.framelayout.onlayout(framelayout.java:388) @ android.view.view.layout(view.java:14841) @ android.view.viewgroup.layout(viewgroup.java:4631) @ android.widget.framelayout.layoutchildren(framelayout.java:453) @ android.widget.framelayout.onlayout(framelayout.java:388) @ android.view.view.layout(view.java:14841) @ android.view.viewgroup.layout(viewgroup.java:4631) @ android.widget.framelayout.layoutchildren(framelayout.java:453) @ android.widget.framelayout.onlayout(framelayout.java:388) @ android.view.view.layout(view.java:14841) @ android.view.viewgroup.layout(viewgroup.java:4631) @ android.widget.framelayout.layoutchildren(framelayout.java:453) @ android.widget.framelayout.onlayout(framelayout.java:388) @ android.view.view.layout(view.java:14841) @ android.view.viewgroup.layout(viewgroup.java:4631) @ android.support.v7.internal.widget.actionbaroverlaylayout.onlayout(actionbaroverlaylayout.java:502) @ android.view.view.layout(view.java:14841) @ android.view.viewgroup.layout(viewgroup.java:4631) @ android.widget.framelayout.layoutchildren(framelayout.java:453) @ android.widget.framelayout.onlayout(framelayout.java:388) @ android.view.view.layout(view.java:14841) @ android.view.viewgroup.layout(viewgroup.java:4631) @ android.widget.linearlayout.setchildframe(linearlayout.java:1717) @ android.widget.linearlayout.layoutvertical(linearlayout.java:1571) @ android.widget.linearlayout.onlayout(linearlayout.java:1480) @ android.view.view.layout(view.java:14841) @ android.view.viewgroup.layout(viewgroup.java:4631) @ android.widget.framelayout.layoutchildren(framelayout.java:453) @ android.widget.framelayout.onlayout(framelayout.java:388) @ android.view.view.layout(view.java:14841) @ android.view.viewgroup.layout(viewgroup.java:4631) @ android.view.viewrootimpl.performlayout(viewrootimpl.java:1986) @ android.view.viewrootimpl.performtraversals(viewrootimpl.java:1743) @ android.view.viewrootimpl.dotraversal(viewrootimpl.java:996) @ android.view.viewrootimpl$traversalrunnable.run(viewrootimpl.java:5603) @ android.view.choreographer$callbackrecord.run(choreographer.java:761) @ android.view.choreographer.docallbacks(choreographer.java:574) @ android.view.choreographer.doframe(choreographer.java:544) @ android.view.choreographer$framedisplayeventreceiver.run(choreographer.java:747) @ android.os.handler.handlecallback(handler.java:733) @ android.os.handler.dispatchmessage(handler.java:95) @ android.os.looper.loop(looper.java:136) @ android.app.activitythread.main(activitythread.java:5146) @ java.lang.reflect.method.invokenative(native method) @ java.lang.reflect.method.invoke(method.java:515) @ com.android.internal.os.zygoteinit$methodandargscaller.run(zygoteinit.java:732) @ com.android.internal.os.zygoteinit.main(zygoteinit.java:566) @ dalvik.system.nativestart.main(native method) 03-17 02:22:37.059 14084-14084/me.ashkelon.sunshine i/process﹕ sending signal. pid: 14084 sig: 9
and code class.
package me.ashkelon.sunshine; import android.content.intent; import android.content.sharedpreferences; import android.net.uri; import android.os.asynctask; import android.os.bundle; import android.preference.preferencemanager; import android.support.v4.app.fragment; import android.text.format.time; import android.util.log; import android.view.layoutinflater; import android.view.menu; import android.view.menuinflater; import android.view.menuitem; import android.view.view; import android.view.viewgroup; import android.widget.adapterview; import android.widget.arrayadapter; import android.widget.listview; import org.json.jsonarray; import org.json.jsonexception; import org.json.jsonobject; import java.io.bufferedreader; import java.io.ioexception; import java.io.inputstream; import java.io.inputstreamreader; import java.net.httpurlconnection; import java.net.url; import java.text.simpledateformat; import java.util.arraylist; import java.util.arrays; import java.util.list; /** * placeholder fragment containing simple view. */ public class forecastfragment extends fragment { private arrayadapter<string> forecastadapter; public forecastfragment() { } @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); //handle menu events (has options) sethasoptionsmenu(true); } @override public void oncreateoptionsmenu(menu menu, menuinflater inflater) { inflater.inflate(r.menu.menu_forecast, menu); } @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { // create dummy data listview. here's sample weekly forecast string[] data = { "mon 6/23 - sunny - 31/17", "tue 6/24 - foggy - 21/8", "wed 6/25 - cloudy - 22/17", "thurs 6/26 - rainy - 18/11", "fri 6/27 - foggy - 21/10", "sat 6/28 - trapped in weatherstation - 23/18", "sun 6/29 - sunny - 20/7" }; list<string> weekforecast = new arraylist<string>(arrays.aslist(data)); // have dummy forecast data, create arrayadapter. // arrayadapter take data source (like our dummy forecast) , // use populate listview it's attached to. forecastadapter = new arrayadapter<string>( getactivity(), // current context (this activity) r.layout.list_item_forecast, // name of layout id. r.id.list_item_forecast_textview, // id of textview populate. weekforecast); view rootview = inflater.inflate(r.layout.fragment_main, container, false); // reference listview, , attach adapter it. listview listview = (listview) rootview.findviewbyid(r.id.listview_forecast); listview.setadapter(forecastadapter); listview.setonitemclicklistener(new adapterview.onitemclicklistener(){ @override public void onitemclick(adapterview<?> parent, view view, int position, long id) { string forecast = forecastadapter.getitem(position); intent intent = new intent(getactivity(),detailactivity.class) .putextra(intent.extra_text, forecast); startactivity(intent); } }); return rootview; } @override public boolean onoptionsitemselected(menuitem item) { int id = item.getitemid(); if(id==r.id.action_refresh){ fetchweathertask fetch = new fetchweathertask(); sharedpreferences pref = preferencemanager.getdefaultsharedpreferences(getactivity()); string location = pref.getstring(getstring(r.string.pref_location_key), getstring(r.string.pref_location_default)); fetch.execute(location); return true; } if(id==r.id.action_settings){ intent intent = new intent(getactivity(),settingsactivity.class); startactivity(intent); return true; } if (id == r.id.action_settings) { intent intent = new intent(getactivity(), settingsactivity.class); startactivity(intent); return true; } return super.onoptionsitemselected(item); } ////////////////////////////////////////////////////////////////////////////// /////////////////////////// data api/////////////////////////////////// ////////////////////////////////////////////////////////////////////////// public class fetchweathertask extends asynctask<string,void,string[]> { private final string log_tag = fetchweathertask.class.getsimplename(); @override protected string[] doinbackground(string... params) { // these 2 need declared outside try/catch // can closed in block. httpurlconnection urlconnection = null; bufferedreader reader = null; // contain raw json response string. string forecastjsonstr = null; string format="json"; string units = "metric"; int numdays =7; try { // construct url openweathermap query // possible parameters available @ owm's forecast api page, @ // http://openweathermap.org/api#forecast final string forecast_base_url = "http://api.openweathermap.org/data/2.5/forecast/daily?"; final string query_param = "q"; final string format_param = "mode"; final string units_param = "units"; final string days_param = "cnt"; uri builturi = uri.parse(forecast_base_url).buildupon() .appendqueryparameter(query_param, params[0]) .appendqueryparameter(format_param, format) .appendqueryparameter(units_param, units) .appendqueryparameter(days_param, integer.tostring(numdays)) .build(); url url = new url(builturi.tostring()); // create request openweathermap, , open connection urlconnection = (httpurlconnection) url.openconnection(); urlconnection.setrequestmethod("get"); urlconnection.connect(); // read input stream string inputstream inputstream = urlconnection.getinputstream(); stringbuffer buffer = new stringbuffer(); if (inputstream == null) { return null; } reader = new bufferedreader(new inputstreamreader(inputstream)); string line; while ((line = reader.readline()) != null) { // since it's json, adding newline isn't necessary (it won't affect parsing) // make debugging *lot* easier if print out completed // buffer debugging. buffer.append(line + "\n"); } if (buffer.length() == 0) { // stream empty. no point in parsing. return null; } forecastjsonstr = buffer.tostring(); } catch (ioexception e) { log.e(log_tag, "error ", e); // if code didn't weather data, there's no point in attempting // parse it. return null; } finally{ if (urlconnection != null) { urlconnection.disconnect(); } if (reader != null) { try { reader.close(); } catch (final ioexception e) { log.e(log_tag, "error closing stream", e); } } } try{ return getweatherdatafromjson(forecastjsonstr, numdays); }catch(jsonexception e){ log.e(log_tag, e.getmessage(), e); e.printstacktrace(); } return null; } /* date/time conversion code going moved outside asynctask later, * convenience we're breaking out own method now. */ private string getreadabledatestring(long time){ // because api returns unix timestamp (measured in seconds), // must converted milliseconds in order converted valid date. simpledateformat shorteneddateformat = new simpledateformat("eee mmm dd"); return shorteneddateformat.format(time); } /** * prepare weather high/lows presentation. */ private string formathighlows(double high, double low) { // presentation, assume user doesn't care tenths of degree. long roundedhigh = math.round(high); long roundedlow = math.round(low); string highlowstr = roundedhigh + "/" + roundedlow; return highlowstr; } /** * take string representing complete forecast in json format , * pull out data need construct strings needed wireframes. * * fortunately parsing easy: constructor takes json string , converts * object hierarchy us. */ //////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /////////////////////////// parse json/////////////////////////////////// ////////////////////////////////////////////////////////////////////////// private string[] getweatherdatafromjson(string forecastjsonstr, int numdays) throws jsonexception { // these names of json objects need extracted. final string owm_list = "list"; final string owm_weather = "weather"; final string owm_temperature = "temp"; final string owm_max = "max"; final string owm_min = "min"; final string owm_description = "main"; jsonobject forecastjson = new jsonobject(forecastjsonstr); jsonarray weatherarray = forecastjson.getjsonarray(owm_list); // owm returns daily forecasts based upon local time of city being // asked for, means need know gmt offset translate data // properly. // since data sent in-order , first day // current day, we're going take advantage of nice // normalized utc date of our weather. time daytime = new time(); daytime.settonow(); // start @ day returned local time. otherwise mess. int julianstartday = time.getjulianday(system.currenttimemillis(), daytime.gmtoff); // work exclusively in utc daytime = new time(); string[] resultstrs = new string[numdays]; for(int = 0; < weatherarray.length(); i++) { // now, using format "day, description, hi/low" string day; string description; string highandlow; // json object representing day jsonobject dayforecast = weatherarray.getjsonobject(i); // date/time returned long. need convert // human-readable, since people won't read "1400356800" // "this saturday". long datetime; // cheating convert utc time, want anyhow datetime = daytime.setjulianday(julianstartday+i); day = getreadabledatestring(datetime); // description in child array called "weather", 1 element long. jsonobject weatherobject = dayforecast.getjsonarray(owm_weather).getjsonobject(0); description = weatherobject.getstring(owm_description); // temperatures in child object called "temp". try not name variables // "temp" when working temperature. confuses everybody. jsonobject temperatureobject = dayforecast.getjsonobject(owm_temperature); double high = temperatureobject.getdouble(owm_max); double low = temperatureobject.getdouble(owm_min); highandlow = formathighlows(high, low); resultstrs[i] = day + " - " + description + " - " + highandlow; } (string s : resultstrs) { } return resultstrs; } @override protected void onpostexecute(string[] result) { if(result != null){ log.v(log_tag, result[0]); forecastadapter.clear(); for(string dayforecaststr : result) { forecastadapter.add(dayforecaststr); } log.v(log_tag, result[0]); } } } }
i realize it's problem adapter update via onpostexecute() can't figure out line causes exception or null coming :(
your observation right! fixed issue setting length of 'resultstrs' 'weatherarray.length()' shown in code snippet.
// work exclusively in utc daytime = new time(); string[] resultstrs = new string[weatherarray.length()]; for(int = 0; < weatherarray.length(); i++) {
Comments
Post a Comment