使用AsyncTask从解析的JSON对象设置文本
使用AsyncTask从解析的JSON对象设置文本
我正在制作一个Android程序,从互联网上的网页源代码中解析JSON文本。它在Android 2.2上工作正常,但现在我需要它在Android 3.0上运行,这需要使用AsyncTask。我对AsyncTask有一些了解,但我不知道把它放在哪里。提前感谢大家的帮助:)\n这是MainActivity类中的方法:\n
private void jsonStuffs() { //JSON解析器和主页文本视图 client = new DefaultHttpClient(); GetMethodEx test = new GetMethodEx(); String returned; try { returned = test.getInternetData(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } try{ String jsonStr = test.getInternetData(); //转到GetMethodEx JSONObject obj = new JSONObject(jsonStr); //////////////////////在网页中的JSON中找到温度 String temperature = obj.getString("temperature"); TextView tvTemp = (TextView)findViewById(R.id.textView); tvTemp.setText(temperature); } //catch (JSONException e) { // e.printStackTrace(); //} catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
\nGetMethodEx类如下(它将找到网页的链接,然后将其源代码转换为文本格式):\n
public class GetMethodEx extends Activity { public String getInternetData() throws Exception{ BufferedReader in = null; String data = null; // try{ HttpClient client = new DefaultHttpClient(); URI website = new URI("http://nhjkv.comuf.com/json_only.php"); HttpGet request = new HttpGet(); request.setURI(website); HttpResponse response = client.execute(request); in = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); StringBuffer sb = new StringBuffer(""); String l = ""; String nl = System.getProperty("line.separator"); while ((l = in.readLine()) !=null){ sb.append(l + nl); } in.close(); data = sb.toString(); return data; }finally { if (in !=null){ try{ in.close(); return data; } catch (Exception e){ e.printStackTrace(); } } } } }
问题的原因是在Android 3.0(Honeycomb)及以上版本中,如果在主线程中进行网络请求而没有使用Thread(例如AsyncTask)进行封装的话,就会报NetworkOnMainThreadException异常。
解决方法是将网络请求的逻辑放在AsyncTask的doInBackground()方法中,即在你的情况下,在doInBackground()方法中调用getInternetData()方法。需要注意的是,在doInBackground()方法中进行长时间运行的任务时,不能直接更新UI。如果想要更新UI,可以采用以下两种方法之一:
1. 在onPostExecute()方法中更新UI。
2. 在doInBackground()方法中使用runOnUiThread()方法进行更新。
这样就可以解决在Android 3.0及以上版本中进行网络请求而出现的问题。
问题的出现原因:
在这段代码中, AsyncTask 类的 onPostExecute 方法中尝试去设置一个 TextView 的文本内容,但是在此之前并没有找到 TextView 的实例。所以会导致程序运行时出现错误。
解决方法:
为了解决这个问题,需要在 AsyncTask 类的构造函数中传入一个 TextView 的实例,并在 onPostExecute 方法中使用这个实例来设置文本内容。
以下是修改后的代码:
class MyAsyncTask extends AsyncTask<String, Void, JSONObject> { private TextView tvTemp; MyAsyncTask(TextView tvTemp) { this.tvTemp = tvTemp; } protected void onPreExecute() { // You can set your activity to show busy indicator //setProgressBarIndeterminateVisibility(true); } protected JSONObject doInBackground(String... args) { return jsonStuffs(); } protected void onPostExecute(final JSONObject jsonObj) { String temperature = jsonObj.getString("temperature"); tvTemp.setText(temperature); // Stop busy indicator //setProgressBarIndeterminateVisibility(false); } }
调用这个任务的方法是 new MyAsyncTask(tvTemp).execute();
,其中 tvTemp 是一个 TextView 的实例。
同时,还需要修改 jsonStuffs 方法,使其返回一个 JSONObject 对象。
修改后的代码如下:
private JSONObject jsonStuffs() { // ... String jsonStr = test.getInternetData(); //go to GetMethodEx return new JSONObject(jsonStr); // ... }