2012-11-20 106 views
1

我試圖從URL中獲取JSON字符串,但我不斷收到「NetworkOnMainThreadException」。我以爲我把我的網絡代碼移到另一個線程,但顯然不是。檢索JSON對象Android

以下是錯誤:error

JSONParser

package com.example.jsonparsing; 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.UnsupportedEncodingException; 

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.params.BasicHttpParams; 
import org.json.JSONException; 
import org.json.JSONObject; 

import android.util.Log; 

public class JSONParser { 

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

    // constructor 
    public JSONParser() { 

    } 

    public String getJSONFromUrl(String url) { 

     DefaultHttpClient httpclient = new DefaultHttpClient(new BasicHttpParams()); 
     HttpPost httppost = new HttpPost("http://api.androidhive.info/contacts/"); 
     // Depends on your web service 
     httppost.setHeader("Content-type", "application/json"); 

     InputStream inputStream = null; 
     String result = null; 
     HttpResponse response = null; 
     try { 
      response = httpclient.execute(httppost); 
     } catch (ClientProtocolException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     }   
     HttpEntity entity = response.getEntity(); 

     try { 
      inputStream = entity.getContent(); 
     } catch (IllegalStateException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     // json is UTF-8 by default i beleive 
     BufferedReader reader = null; 
     try { 
      reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8); 
     } catch (UnsupportedEncodingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     StringBuilder sb = new StringBuilder(); 

     String line = null; 
     try { 
      while ((line = reader.readLine()) != null) 
      { 
       sb.append(line + "\n"); 
      } 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     return result = sb.toString(); 
    } 
} 

主要活動

package com.example.jsonparsing; 

import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.Map; 

import org.json.JSONArray; 
import org.json.JSONException; 
import org.json.JSONObject; 

import android.os.Bundle; 
import android.app.Activity; 
import android.content.Intent; 
import android.util.Log; 
import android.view.Menu; 
import android.view.View; 
import android.widget.AdapterView; 
import android.widget.ListAdapter; 
import android.widget.ListView; 
import android.widget.SimpleAdapter; 
import android.widget.TextView; 

public class MainActivity extends Activity{ 

    // url to make request 
    private static String url = "http://api.androidhive.info/contacts/"; 

    // contacts JSONArray 
    JSONArray contacts = null; 

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

     // Hashmap for ListView 
     ArrayList<HashMap<String, String>> contactList = new ArrayList<HashMap<String, String>>(); 

     RetrieveJSONString retrieveJSON = new RetrieveJSONString(); 
     retrieveJSON.run(); 
     String whatever = retrieveJSON.getJSONString(); 
    } 
} 

class RetrieveJSONString implements Runnable{ 

    JSONParser jParser; 
    String jsonString; 

    public void run() { 
     // Creating JSON Parser instance 
     JSONParser jParser = new JSONParser(); 

     // getting JSON string from URL 
     String jsonString = jParser.getJSONFromUrl("http://api.androidhive.info/contacts/"); 

    } 

    public String getJSONString(){ 

     return jsonString; 
    } 

} 

清單

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.example.jsonparsing" 
    android:versionCode="1" 
    android:versionName="1.0" > 

    <uses-sdk 
     android:minSdkVersion="16" 
     android:targetSdkVersion="15" /> 
    <uses-permission android:name="android.permission.INTERNET"/> 

    <application 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" 
     android:theme="@style/AppTheme" > 
     <activity 
      android:name=".MainActivity" 
      android:label="@string/title_activity_main" > 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 

</manifest> 

如果有人能提供一些線索有限公關於這個問題,我將不勝感激!

+1

你可以發佈錯誤堆棧嗎?和你的Android Manifest文件。 – PearsonArtPhoto

+0

已更新,錯誤與清單 – TomSelleck

回答

4

你得到這個錯誤,因爲你正試圖在UI線程上執行HTTP調用調用這個AscyTask任務,你永遠不應該這樣做:)使用一個替代的AsyncTask。這裏有一個簡單的例子:

GetJsonAsync getJson = new GetJsonAsync(); 
getJson.execute(); 

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

     @Override 
     protected void onPreExecute() { 
      // Do stuff before the operation 
     } 

     @Override 
     protected String doInBackground(String... params){ 
      getJSONFromUrl(); 
      return null; 
     } 

     @Override 
     protected void onPostExecute(String result) { 
      // Do stuff after the operation 
     } 
    } 
+0

順便說一句這個類需要在你的活動,所以你將不得不instaniate你的JSONparser在那裏,並從它調用getJSONFromURL。使Runnable不會在單獨的線程上運行,除非將其分配給線程。 – DecodeGnome

3

Android SDK docs

The exception that is thrown when an application attempts to perform a networking operation on its main thread.

This is only thrown for applications targeting the Honeycomb SDK or higher. Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads, but it's heavily discouraged. See the document Designing for Responsiveness.

從本質上講,你想要做某種線程化應用的,否則GUI可以卡住。看看AsyncTask或者只是爲你的JSON解析需求進行線程化。

3

您應該致電start()Thread而不是直接調用run方法。您正在調用將在UI線程上運行的retrieveJSON.run();

new Thread(new RetrieveJSONString()).start(); 

我建議使用用於此目的,而不是一個線程一個AsyncTask,只要你想獲取JSON之後更新UI。在AsyncTask中,當後臺作業完成時,將調用onPOstExecute()方法,您可以在其中更新UI。

+0

現在嘗試此操作,但「此方法start()未定義類型RetrieveJSONString」 – TomSelleck

+0

調用Thread類不在Runnable .. – Ronnie

+0

使用此:'RetrieveJSONString retrieveJSON = new RetrieveJSONString();新線程(retrieveJSON).start();' – nhaarman

0

致電getJSONFromUrl方法裏面的AscyTask。這個異常發生在進程花費很長時間。通過這條線

new AppTask().execute();

public class AppTask extends AsyncTask<String, String, Void> { 
    protected void onProgressUpdate(String... progress){} protected void onPreExecute(){ } 

    protected Void doInBackground(final String... args) { 
     getJSONFromUrl(); 
     return null; 
    } 

    protected void onPostExecute(final Void unused) { } 
} 
+0

這不是因爲它需要很長時間。看到我的答案。此外,你的代碼不工作:) – DecodeGnome