1

我正在尝试解析 JSON,我正在使用这个示例

在类解析器的示例中,没有使用辅助线程,我得到NetworkOnMainThreadException

为了解决这个问题,我在 Asynctask 中引入了代码,但由于在线出现错误而无法正确传输数据:

contacts = json.getJSONArray(TAG_CONTACTS);

这是我正在使用的简单代码

JSONParser.java

public class JSONParser {

    static InputStream is = null;
    static JSONObject jObj = null;
    static String json = "";

    // constructor
    public JSONParser() {

    }

    public JSONObject getJSONFromUrl(String url) {
        new ParseJson().execute(url);
        return jObj;
    }

    private class ParseJson extends AsyncTask<String, Void, JSONObject>{

         protected JSONObject doInBackground(String... params) {
             // Making HTTP request
             try {
                 // defaultHttpClient
                 DefaultHttpClient httpClient = new DefaultHttpClient();
                 HttpPost httpPost = new HttpPost(params[0]);

                 HttpResponse httpResponse = httpClient.execute(httpPost);
                 HttpEntity httpEntity = httpResponse.getEntity();
                 is = httpEntity.getContent();           
             } catch (UnsupportedEncodingException e) {
                 e.printStackTrace();
             } catch (ClientProtocolException e) {
                 e.printStackTrace();
             } catch (IOException e) {
                 e.printStackTrace();
             }

             try {
                 BufferedReader reader = new BufferedReader(new InputStreamReader(
                         is, "iso-8859-1"), 8);
                 StringBuilder sb = new StringBuilder();
                 String line = null;
                 while ((line = reader.readLine()) != null) {
                     sb.append(line + "\n");
                 }
                 is.close();

                 json = sb.toString();
             } catch (Exception e) {
                 Log.e("Buffer Error", "Error converting result " + e.toString());
             }

             // try parse the string to a JSON object
             try {
                 jObj = new JSONObject(json);
             } catch (JSONException e) {
                 Log.e("JSON Parser", "Error parsing data " + e.toString());
             }

             // return JSON String
             return jObj;
         }
   }
}

MainActivity.java

public class MainActivity extends Activity{
 // url to make request
private static String url = "http://api.androidhive.info/contacts/";

// JSON Node names
private static final String TAG_CONTACTS = "contacts";
private static final String TAG_ID = "id";
private static final String TAG_NAME = "name";


// contacts JSONArray
JSONArray contacts = null;
JSONObject json;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    new task().execute();
}

public void loadAreas(){
    try {

        // looping through All Contacts
        for(int i = 0; i < contacts.length(); i++){
            JSONObject c = contacts.getJSONObject(i);

            // Storing each json item in variable
            String id = c.getString(TAG_ID);
            String name = c.getString(TAG_NAME);

            Log.e("TAG","ID: "+id+" - "+"NAME: "+name);
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
}          

private class task extends AsyncTask<String, Void, String> {

    @Override
    protected String doInBackground(String... params) {  
        try {
        // Creating JSON Parser instance
        JSONParser jParser = new JSONParser();

        // getting JSON string from URL
        JSONObject json = jParser.getJSONFromUrl(url);

        // Getting Array of Contacts
            contacts = json.getJSONArray(TAG_CONTACTS);

        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }
    @Override
    protected void onPostExecute(String result) {
        loadAreas();
    }

}

}

我的JSON数据

{
    "contacts": [
        {
                "id": "c200",
                "name": "Ravi Tamada",
                "email": "ravi@gmail.com",
                "address": "xx-xx-xxxx,x - street, x - country",
                "gender" : "male",
                "phone": {
                    "mobile": "+91 0000000000",
                    "home": "00 000000",
                    "office": "00 000000"
                }
        },
        {
                "id": "c201",
                "name": "Johnny Depp",
                "email": "johnny_depp@gmail.com",
                "address": "xx-xx-xxxx,x - street, x - country",
                "gender" : "male",
                "phone": {
                    "mobile": "+91 0000000000",
                    "home": "00 000000",
                    "office": "00 000000"
                }
        },
        {
                "id": "c202",
                "name": "Leonardo Dicaprio",
                "email": "leonardo_dicaprio@gmail.com",
                "address": "xx-xx-xxxx,x - street, x - country",
                "gender" : "male",
                "phone": {
                    "mobile": "+91 0000000000",
                    "home": "00 000000",
                    "office": "00 000000"
                }
        },
        {
                "id": "c203",
                "name": "John Wayne",
                "email": "john_wayne@gmail.com",
                "address": "xx-xx-xxxx,x - street, x - country",
                "gender" : "male",
                "phone": {
                    "mobile": "+91 0000000000",
                    "home": "00 000000",
                    "office": "00 000000"
                }
        },
        {
                "id": "c204",
                "name": "Angelina Jolie",
                "email": "angelina_jolie@gmail.com",
                "address": "xx-xx-xxxx,x - street, x - country",
                "gender" : "female",
                "phone": {
                    "mobile": "+91 0000000000",
                    "home": "00 000000",
                    "office": "00 000000"
                }
        },
        {
                "id": "c205",
                "name": "Dido",
                "email": "dido@gmail.com",
                "address": "xx-xx-xxxx,x - street, x - country",
                "gender" : "female",
                "phone": {
                    "mobile": "+91 0000000000",
                    "home": "00 000000",
                    "office": "00 000000"
                }
        },
        {
                "id": "c206",
                "name": "Adele",
                "email": "adele@gmail.com",
                "address": "xx-xx-xxxx,x - street, x - country",
                "gender" : "female",
                "phone": {
                    "mobile": "+91 0000000000",
                    "home": "00 000000",
                    "office": "00 000000"
                }
        },
        {
                "id": "c207",
                "name": "Hugh Jackman",
                "email": "hugh_jackman@gmail.com",
                "address": "xx-xx-xxxx,x - street, x - country",
                "gender" : "male",
                "phone": {
                    "mobile": "+91 0000000000",
                    "home": "00 000000",
                    "office": "00 000000"
                }
        },
        {
                "id": "c208",
                "name": "Will Smith",
                "email": "will_smith@gmail.com",
                "address": "xx-xx-xxxx,x - street, x - country",
                "gender" : "male",
                "phone": {
                    "mobile": "+91 0000000000",
                    "home": "00 000000",
                    "office": "00 000000"
                }
        },
        {
                "id": "c209",
                "name": "Clint Eastwood",
                "email": "clint_eastwood@gmail.com",
                "address": "xx-xx-xxxx,x - street, x - country",
                "gender" : "male",
                "phone": {
                    "mobile": "+91 0000000000",
                    "home": "00 000000",
                    "office": "00 000000"
                }
        },
        {
                "id": "c2010",
                "name": "Barack Obama",
                "email": "barack_obama@gmail.com",
                "address": "xx-xx-xxxx,x - street, x - country",
                "gender" : "male",
                "phone": {
                    "mobile": "+91 0000000000",
                    "home": "00 000000",
                    "office": "00 000000"
                }
        },
        {
                "id": "c2011",
                "name": "Kate Winslet",
                "email": "kate_winslet@gmail.com",
                "address": "xx-xx-xxxx,x - street, x - country",
                "gender" : "female",
                "phone": {
                    "mobile": "+91 0000000000",
                    "home": "00 000000",
                    "office": "00 000000"
                }
        },
        {
                "id": "c2012",
                "name": "Eminem",
                "email": "eminem@gmail.com",
                "address": "xx-xx-xxxx,x - street, x - country",
                "gender" : "male",
                "phone": {
                    "mobile": "+91 0000000000",
                    "home": "00 000000",
                    "office": "00 000000"
                }
        }
    ]
}

日志猫

04-01 16:06:48.414: W/dalvikvm(9151): threadid=11: thread exiting with uncaught exception (group=0x40d09930)
04-01 16:06:48.422: E/AndroidRuntime(9151): FATAL EXCEPTION: AsyncTask #1
04-01 16:06:48.422: E/AndroidRuntime(9151): java.lang.RuntimeException: An error occured while executing doInBackground()
04-01 16:06:48.422: E/AndroidRuntime(9151):     at android.os.AsyncTask$3.done(AsyncTask.java:299)
04-01 16:06:48.422: E/AndroidRuntime(9151):     at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
04-01 16:06:48.422: E/AndroidRuntime(9151):     at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
04-01 16:06:48.422: E/AndroidRuntime(9151):     at java.util.concurrent.FutureTask.run(FutureTask.java:239)
04-01 16:06:48.422: E/AndroidRuntime(9151):     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
04-01 16:06:48.422: E/AndroidRuntime(9151):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
04-01 16:06:48.422: E/AndroidRuntime(9151):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
04-01 16:06:48.422: E/AndroidRuntime(9151):     at java.lang.Thread.run(Thread.java:856)
04-01 16:06:48.422: E/AndroidRuntime(9151): Caused by: java.lang.NullPointerException
04-01 16:06:48.422: E/AndroidRuntime(9151):     at com.example.json_parser.MainActivity$task.doInBackground(MainActivity.java:63)
04-01 16:06:48.422: E/AndroidRuntime(9151):     at com.example.json_parser.MainActivity$task.doInBackground(MainActivity.java:1)
04-01 16:06:48.422: E/AndroidRuntime(9151):     at android.os.AsyncTask$2.call(AsyncTask.java:287)
04-01 16:06:48.422: E/AndroidRuntime(9151):     at java.util.concurrent.FutureTask.run(FutureTask.java:234)
04-01 16:06:48.422: E/AndroidRuntime(9151):     ... 4 more
04-01 16:06:48.461: D/libEGL(9151): loaded /vendor/lib/egl/libEGL_POWERVR_SGX540_120.so
04-01 16:06:48.476: D/libEGL(9151): loaded /vendor/lib/egl/libGLESv1_CM_POWERVR_SGX540_120.so
04-01 16:06:48.484: D/libEGL(9151): loaded /vendor/lib/egl/libGLESv2_POWERVR_SGX540_120.so
04-01 16:06:48.570: D/OpenGLRenderer(9151): Enabling debug mode 0
04-01 16:06:50.273: D/dalvikvm(9151): GC_CONCURRENT freed 182K, 3% free 8885K/9100K, paused 3ms+23ms, total 41ms

我有那个问题?

我错误地返回 Json 对象?

谢谢!

4

4 回答 4

1

顾名思义,AsyncTask异步执行任务。这意味着它不会阻止执行,因此:

    JSONParser jParser = new JSONParser();

    // getting JSON string from URL
    JSONObject json = jParser.getJSONFromUrl(url);

您返回的jParser.getJsonFromUrl(url)值为 null。AsyncTaskdoInBackground()尚未执行。

您需要将解析代码移动到doInBackground(),然后将任何更新 UI 的代码移动到onPostExecute().

于 2013-04-01T13:21:31.013 回答
0

问题是您试图在后台线程完成工作之前使用您的对象。您应该使用 AsyncTask 的onPostExecute方法,如下所示:

        @Override
        protected void onPostExecute(JSONObject result)
        {
            super.onPostExecute(result);
            // use your "result" JSONObject for whatever purposes, it's ready now
        }
于 2013-04-01T13:27:04.400 回答
0

我猜这里的问题是您正在获取响应。doInBackground尝试将转换为的逻辑JSONObject与 doInBackground 分开

将类的返回类型更改doInBackground为并剪切此代码:JSONParservoid

  try {
                 BufferedReader reader = new BufferedReader(new InputStreamReader(
                         is, "iso-8859-1"), 8);
                 StringBuilder sb = new StringBuilder();
                 String line = null;
                 while ((line = reader.readLine()) != null) {
                     sb.append(line + "\n");
                 }
                 is.close();

                 json = sb.toString();
             } catch (Exception e) {
                 Log.e("Buffer Error", "Error converting result " + e.toString());
             }

             // try parse the string to a JSON object
             try {
                 jObj = new JSONObject(json);
             } catch (JSONException e) {
                 Log.e("JSON Parser", "Error parsing data " + e.toString());
             }

             // return JSON String
             return jObj;

并将其放入并将其返回类型更改为onPostExecuteJSONObjectParseJson

试试这个并恢复

于 2013-04-01T14:34:33.950 回答
0

您正在尝试在启动异步操作后立即读取它的结果。

我建议您在活动中创建回调方法,以便AsyncTask在后台工作完成时通知活动。

像这样的东西:

// Callback interface
public interface JSONParserListener {
    void onEndGettingJSON(JSONObject resultJSONObject);
}

// In JSONParser class
public class JSONParser {
    private final JSONParserListener listener;

    public JSONParser(final JSONParserListener listener) {
         this.listener = listener;
    }

    // At the end of getting json just callback listener with result
    listener.onEndGettingJSON(jObj);
}

// Your activity should implement JSONParserListener
// Catch result in onEndGettingJSON() method

public class MainActivity extends Activity implements JSONParserListener {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        // Your code...
        // Creating JSON Parser instance WITH CALLBACK LISTENER
        JSONParser jParser = new JSONParser(this);
        jParser.getJSONFromUrl(url);
    }

    // Callback handler
    public void onEndGettingJSON(final JSONObject resultJSON) {
        // Here you can do what you want with downloaded JSON :)
    }
}

另外,我建议您将JSONParser类重命名为类似的名称,JSONDowloadTask因为当我看到名为的类时,JSONParser我认为它应该只解析 JSON 并将解析的实体返回给我,但您JSONParser实际上是 DOWNLOAD (O_o) JSON :)

于 2013-04-01T13:21:45.423 回答