2012-10-05 84 views
2

有人可能請檢查代碼。我的XMLParser發現了一個異常。我試圖使用帶有XML解析器的listview來分析來自遠程數據庫的結果。Android XML解析器異常捕獲

MainActivity.java

public class MainActivity extends SherlockFragmentActivity implements TabListener { 
    private Fragment mFragment; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     setContentView(R.layout.main); 

     ActionBar actionBar = getSupportActionBar(); 
     actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 
     actionBar.setDisplayShowTitleEnabled(true); 

     //mFragment = new AppleFragment(); 

     Tab tab = actionBar.newTab() 
       .setText("Apple") 
       .setTabListener(this) 
       .setIcon(R.drawable.apple); 

     actionBar.addTab(tab); 


    } 

    @Override 
    public void onTabSelected(Tab tab, FragmentTransaction ft) { 
     if (mFragment == null) { 
       mFragment = new AppleFragment(); 
       ft.add(android.R.id.content, mFragment); 
      } else { 
       ft.attach(mFragment); 
      } 
    } 

    @Override 
    public void onTabUnselected(Tab tab, FragmentTransaction ft) { 
     ft.detach(mFragment); 
    } 

    @Override 
    public void onTabReselected(Tab tab, FragmentTransaction ft) { 
    } 
} 

AppleFragment.java

public class AppleFragment extends SherlockListFragment{ 


     static final String URL = "http://api.androidhive.info/pizza/?format=xml"; 
     // XML node keys 
     static final String KEY_ITEM = "item"; // parent node 
     static final String KEY_ID = "id"; 
     static final String KEY_NAME = "name"; 
     static final String KEY_COST = "cost"; 
     static final String KEY_DESC = "description"; 



     @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){ 

     return super.onCreateView(inflater, container, savedInstanceState); 

     } 


     public void onActivityCreated(Bundle savedInstanceState) { 

      ArrayList<HashMap<String, String>> menuItems = new ArrayList<HashMap<String, String>>(); 


      XMLParser parser = new XMLParser(); 
      String xml = parser.getXmlFromUrl(URL); // getting XML 
      Document doc = parser.getDomElement(xml); // getting DOM element 

      NodeList nl = doc.getElementsByTagName(KEY_ITEM); 
      // looping through all item nodes <item> 
      for (int i = 0; i < nl.getLength(); i++) { 
       // creating new HashMap 
       HashMap<String, String> map = new HashMap<String, String>(); 
       Element e = (Element) nl.item(i); 
       // adding each child node to HashMap key => value 
       map.put(KEY_ID, parser.getValue(e, KEY_ID)); 
       map.put(KEY_NAME, parser.getValue(e, KEY_NAME)); 
       map.put(KEY_COST, "Rs." + parser.getValue(e, KEY_COST)); 
       map.put(KEY_DESC, parser.getValue(e, KEY_DESC)); 

       // adding HashList to ArrayList 
       menuItems.add(map); 
      } 

      ListAdapter adapter = new SimpleAdapter(getActivity(), menuItems, 
        R.layout.list_item, 
        new String[] { KEY_NAME, KEY_DESC, KEY_COST }, new int[] { 
          R.id.name, R.id.desciption, R.id.cost }); 


      setListAdapter(adapter);  


     } 
} 

XMLParser.java

public class XMLParser { 

    // constructor 
    public XMLParser() { 

    } 

    /** 
    * Getting XML from URL making HTTP request 
    * @param url string 
    * */ 
    public String getXmlFromUrl(String url) { 
     String xml = null; 

     try { 
      // defaultHttpClient 
      DefaultHttpClient httpClient = new DefaultHttpClient(); 
      HttpPost httpPost = new HttpPost(url); 

      HttpResponse httpResponse = httpClient.execute(httpPost); 
      HttpEntity httpEntity = httpResponse.getEntity(); 
      xml = EntityUtils.toString(httpEntity); 

     } catch (UnsupportedEncodingException e) { 
      e.printStackTrace(); 
     } catch (ClientProtocolException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     // return XML 
     return xml; 
    } 

    /** 
    * Getting XML DOM element 
    * @param XML string 
    * */ 
    public Document getDomElement(String xml){ 
     Document doc = null; 
     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
     try { 

      DocumentBuilder db = dbf.newDocumentBuilder(); 

      InputSource is = new InputSource(); 
       is.setCharacterStream(new StringReader(xml)); 
       doc = db.parse(is); 

      } catch (ParserConfigurationException e) { 
       Log.e("Error: ", e.getMessage()); 
       return null; 
      } catch (SAXException e) { 
       Log.e("Error: ", e.getMessage()); 
       return null; 
      } catch (IOException e) { 
       Log.e("Error: ", e.getMessage()); 
       return null; 
      } 

      return doc; 
    } 

    /** Getting node value 
     * @param elem element 
     */ 
    public final String getElementValue(Node elem) { 
     Node child; 
     if(elem != null){ 
      if (elem.hasChildNodes()){ 
       for(child = elem.getFirstChild(); child != null; child = child.getNextSibling()){ 
        if(child.getNodeType() == Node.TEXT_NODE ){ 
         return child.getNodeValue(); 
        } 
       } 
      } 
     } 
     return ""; 
    } 

    /** 
     * Getting node value 
     * @param Element node 
     * @param key string 
     * */ 
    public String getValue(Element item, String str) {  
      NodeList n = item.getElementsByTagName(str);   
      return this.getElementValue(n.item(0)); 
     } 
} 

logcat的:

10-05 16:36:50.453: E/AndroidRuntime(20162): FATAL EXCEPTION: main 
10-05 16:36:50.453: E/AndroidRuntime(20162): java.lang.RuntimeException: Unable to start activity ComponentInfo{in.wptrafficanalyzer.actionbarsherlocknavtab/in.wptrafficanalyzer.actionbarsherlocknavtab.MainActivity}: android.os.NetworkOnMainThreadException 
10-05 16:36:50.453: E/AndroidRuntime(20162): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1970) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1995) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at android.app.ActivityThread.access$600(ActivityThread.java:127) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1161) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at android.os.Handler.dispatchMessage(Handler.java:99) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at android.os.Looper.loop(Looper.java:137) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at android.app.ActivityThread.main(ActivityThread.java:4512) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at java.lang.reflect.Method.invokeNative(Native Method) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at java.lang.reflect.Method.invoke(Method.java:511) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:982) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:749) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at dalvik.system.NativeStart.main(Native Method) 
10-05 16:36:50.453: E/AndroidRuntime(20162): Caused by: android.os.NetworkOnMainThreadException 
10-05 16:36:50.453: E/AndroidRuntime(20162): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at java.net.InetAddress.lookupHostByName(InetAddress.java:391) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at java.net.InetAddress.getAllByNameImpl(InetAddress.java:242) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at java.net.InetAddress.getAllByName(InetAddress.java:220) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at in.wptrafficanalyzer.actionbarsherlocknavtab.XMLParser.getXmlFromUrl(XMLParser.java:45) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at in.wptrafficanalyzer.actionbarsherlocknavtab.AppleFragment.onCreateView(AppleFragment.java:38) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:870) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1080) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:622) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1416) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:505) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1136) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at android.app.Activity.performStart(Activity.java:4475) 
10-05 16:36:50.453: E/AndroidRuntime(20162): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1943) 
10-05 16:36:50.453: E/AndroidRuntime(20162): ... 11 more 
+0

[鏈接的問題](http://stackoverflow.com/questions/6343166/android-os-networkonmainthreadexception) –

回答

3

您正在主線程上運行網絡操作。使用異步任務在後臺線程中運行網絡操作(在後臺線程中執行xml解析)。這就是爲什麼你得到android.os.NetworkOnMainThreadException。

解析它在一個異步任務是這樣的:

class XMLParsingTask extends AsyncTask<String, Void, RSSFeed> { 


    protected void onPreExecute() { 
    //show a progress dialog to the user or something 
    } 

    protected void doInBackground(String... urls) { 
     //Parse your XML here 
    } 

    protected void onPostExecute() { 
     //do something with your parsed xml here and dismiss the progress dialog 
    } 
} 

new RXMLParsingTask().execute(null); 

下面爲大家介紹一些教程,如果你不知道如何使用異步任務:

http://mobileorchard.com/android-app-developmentthreading-part-2-async-tasks/

http://www.vogella.com/articles/AndroidPerformance/article.html

這裏是官方文檔:https://developer.android.com/reference/android/os/AsyncTask.html

+0

謝謝,我怎麼能忘記...! –

+0

2分鐘後會接受您的答案。被鎖定 –

+0

當然。請儘可能將答案標記爲已接受。謝謝。 –

0

將您的網絡邏輯從主線程移動到單獨的線程。從Android 3.0開始,我們需要在單獨的線程上執行所有與網絡相關的代碼。

+0

謝謝.. Anup Cowkur解決了我的問題。 –