使用AsyncTask从解析的JSON对象设置文本

16 浏览
0 Comments

使用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();
                }
            }
        }
    }
}

0
0 Comments

问题的原因是在Android 3.0(Honeycomb)及以上版本中,如果在主线程中进行网络请求而没有使用Thread(例如AsyncTask)进行封装的话,就会报NetworkOnMainThreadException异常。

解决方法是将网络请求的逻辑放在AsyncTask的doInBackground()方法中,即在你的情况下,在doInBackground()方法中调用getInternetData()方法。需要注意的是,在doInBackground()方法中进行长时间运行的任务时,不能直接更新UI。如果想要更新UI,可以采用以下两种方法之一:

1. 在onPostExecute()方法中更新UI。

2. 在doInBackground()方法中使用runOnUiThread()方法进行更新。

这样就可以解决在Android 3.0及以上版本中进行网络请求而出现的问题。

0
0 Comments

问题的出现原因:

在这段代码中, 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);
     // ...
}

0