java - Error: Only the original thread that created a view hierarchy can touch its views on Android app -
i have activity populates listview
. works correctly. now, want populate listview
using json
text php
script. have adapter objects (locations) , want add location each json
object. when call method add json
data adapter (getdata()
), get:
error parsing data android.view.viewrootimpl$calledfromwrongthreadexception: original thread created view hierarchy can touch views.
what doing wrong , how can fix it? thanks
activity code:
public class mainactivity extends actionbaractivity { arraylist<location> arrayoflocations; locationadapter adapter; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); requestwindowfeature(window.feature_no_title); getwindow().setflags(windowmanager.layoutparams.flag_fullscreen, windowmanager.layoutparams.flag_fullscreen); setcontentview(r.layout.activity_main); // construct data source arrayoflocations = new arraylist<location>(); // create adapter convert array views adapter = new locationadapter(this, arrayoflocations); adapter.add(new location(r.drawable.ic_launcher, "fruit stand", "we have freshest fruit in whole world!", "2 miles", "8-5 mon-sat\nclosed sun")); getdata(); // attach adapter listview listview listview = (listview) findviewbyid(r.id.listview1); view header = (view) getlayoutinflater().inflate( r.layout.listview_header, null); listview.addheaderview(header); listview.setadapter(adapter); } @override public boolean oncreateoptionsmenu(menu menu) { // inflate menu; adds items action bar if present. getmenuinflater().inflate(r.menu.main, menu); return true; } @override public boolean onoptionsitemselected(menuitem item) { // handle action bar item clicks here. action bar // automatically handle clicks on home/up button, long // specify parent activity in androidmanifest.xml. int id = item.getitemid(); if (id == r.id.action_settings) { return true; } return super.onoptionsitemselected(item); } public void getdata() { thread thread = new thread(new runnable() { @override public void run() { string result = ""; inputstream isr = null; try { httpclient httpclient = new defaulthttpclient(); httppost httppost = new httppost( "http://10.0.0.9/examples.php"); // php script // address httpresponse response = httpclient.execute(httppost); httpentity entity = response.getentity(); isr = entity.getcontent(); // resultview.settext("connected"); } catch (exception e) { log.e("log_tag", "error in http connection " + e.tostring()); } // convert response string try { bufferedreader reader = new bufferedreader( new inputstreamreader(isr, "iso-8859-1"), 8); stringbuilder sb = new stringbuilder(); string line = null; while ((line = reader.readline()) != null) { sb.append(line + "\n"); } isr.close(); result = sb.tostring(); } catch (exception e) { log.e("log_tag", "error converting result " + e.tostring()); } // parse json data try { string s = ""; jsonarray jarray = new jsonarray(result); (int = 0; < jarray.length(); i++) { jsonobject json = jarray.getjsonobject(i); s = s + "title : " + json.getstring("placetitle") + " details: " + json.getstring("placedetails") + "\n" + "distance : " + json.getstring("placedistance") + "\n\n"; adapter.add(new location(r.drawable.ic_launcher, json .getstring("placetitle"), json .getstring("placedetails"), json .getstring("placedistance"), "9-6")); } } catch (exception e) { // todo: handle exception log.e("log_tag", "error parsing data " + e.tostring()); } } }); thread.start(); } }
logcat:
05-29 15:56:47.353: d/openglrenderer(19595): enabling debug mode 0 05-29 15:59:09.095: d/libegl(19832): loaded /vendor/lib/egl/libegl_powervr_sgx540_120.so 05-29 15:59:09.119: d/libegl(19832): loaded /vendor/lib/egl/libglesv1_cm_powervr_sgx540_120.so 05-29 15:59:09.127: d/libegl(19832): loaded /vendor/lib/egl/libglesv2_powervr_sgx540_120.so 05-29 15:59:09.213: d/openglrenderer(19832): enabling debug mode 0 05-29 15:59:09.236: i/choreographer(19832): skipped 39 frames! application may doing work on main thread. 05-29 15:59:09.853: e/log_tag(19832): error parsing data android.view.viewrootimpl$calledfromwrongthreadexception: original thread created view hierarchy can touch views.
that's because you're adding adapter
background thread. trigger redraw of of visible views in list can display latest data adapter. however, views can modified ui thread. 1 quick solution wrap addition in runnable , post ui thread:
runonuithread(new runnable() { @override public void run() { adapter.add(new location(r.drawable.ic_launcher, json.getstring("placetitle"), json.getstring("placedetails"), json.getstring("placedistance"), "9-6")); } });
i don't recommend this. use either asynctask
or service
downloads , parses response list<location>
of results, , after completes, , you're on ui thread, add of results @ once.
Comments
Post a Comment