2016-02-23 61 views
-2

我想開發一個應用程序,使我從一個Android應用程序在服務器 這裏文本文件的形式上傳的數據是在MainActivity類的Android應用程序崩潰是由於NetworkOnMainThreadException

package com.example.incrediblemachine.sendtest; 

import android.app.Activity; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
import android.widget.EditText; 
import android.widget.Toast; 

import org.apache.http.NameValuePair; 
import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.entity.UrlEncodedFormEntity; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.message.BasicNameValuePair; 

import java.io.IOException; 
import java.util.ArrayList; 
import java.util.List; 

public class MainActivity extends Activity { 

    EditText msgTextField; 
    Button sendButton; 

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

     //make message text field object 
     msgTextField = (EditText) findViewById(R.id.msgTextField); 
     //make button object 
     sendButton = (Button) findViewById(R.id.sendButton); 
    } 

    public void send(View v) 
    { 
     //get message from message box 
     String msg = msgTextField.getText().toString(); 

     //check whether the msg empty or not 
     if(msg.length()>0) { 
      HttpClient httpclient = new DefaultHttpClient(); 
      HttpPost httppost = new HttpPost("http://ramsproject.16mb.com/sendorder.php"); 

      try { 
       List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); 
       nameValuePairs.add(new BasicNameValuePair("id", "01")); 
       nameValuePairs.add(new BasicNameValuePair("message", msg)); 
       httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); 
       httpclient.execute(httppost); 
       msgTextField.setText(""); //reset the message text field 
       Toast.makeText(getBaseContext(),"Sent",Toast.LENGTH_SHORT).show(); 
      }catch (IllegalStateException e) 
      { 
       e.printStackTrace(); 
      } 
      catch (ClientProtocolException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } else { 
      //display message if text field is empty 
      Toast.makeText(getBaseContext(),"All fields are required",Toast.LENGTH_SHORT).show(); 
     } 
    } 

} 

它有出現第53行的例外 httpclient.execute(httppost);

異常說android.app.NetworkOnMainThreadException 我如何解決這個

+1

使用AsyncTask在後臺進行網絡調用。 –

+1

在AsyncTask中使用此代碼 – curiousMind

+1

Android不允許您在主線程中進行互聯網調用,以免阻止它並提供糟糕的用戶體驗。系統迫使你在另一個線程中執行它......這是你應該做的。 – Fustigador

回答

2

只需使用一個線程。

Thread thread = new Thread(new Runnable(){ 
    @Override 
    public void run() { 
     try { 
      //Your code goes here 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
}); 

thread.start(); 

在此線程中調用httpClient。

+1

或AsyncTask ... – IceJOKER

+0

謝謝!爲我工作 –

+0

隨時歡迎。 –

0

此異常當應用程序試圖在其主線程進行網絡操作時引發。 針對Honeycomb SDK或更高版本的應用程序允許在其主要事件循環線程上進行聯網,以避免在與網絡有關的無響應位置上出現遲緩。你可以參考Documentation

要解決這一點,你有這樣的選擇: 1.使用AsyncTasks 2.線程 3.處理程序

0

我想這裏爲你提供解決方案。爲此,我想在您理解解決方案之前指出幾點。

  1. 所有機器人部件(活動,服務,廣播接收器,片段和任何在視覺上示出的數據)在UI線程或主線程運行,理解這進一步閱讀。

  2. 每個Android應用程序都在其自己的進程上運行並且具有唯一的用戶ID。當安裝了一個android應用程序時,它會被賦予一個唯一的用戶ID。每當應用程序運行時,它都會被分配一個單獨的內存空間和程序執行路徑。這個過程由稱爲Heap的自己的內存組成。該過程就像爲您的應用程序提供運行代碼或流程代碼的獨立環境。

  3. 另一方面,線程是子進程或輕量級進程。它在過程中產生。當創建一個線程時,它會被賦予一部分內存(堆棧)。一個進程可以產生許多線程。

  4. 線程無法訪問另一個線程的內存(堆棧),它對於特定的線程是私有的。但他們可以訪問進程內存(堆內存)。將堆內存視爲全局內存。

  5. 每當爲應用程序創建進程時,都會創建一個單獨的線程,這是強制性的。這個線程被稱爲主線程。在android中它可能也被稱爲UI線程。因爲這個線程處理你看到的所有UI組件(像activity,Fragment和Services(即使服務在後臺運行,它在UI Thread上運行)等等)。

  6. Android框架的創建方式是,他們希望處理主線程上的所有UI操作,從而優先處理UI組件。因爲UI是顯示給用戶的UI,並且如果應用程序在未處理UI的情況下被凍結,用戶將不會喜歡它。

  7. 這就是您得到「NetworkOnMainThread」異常的原因。由於Android限制運行長時間運行的操作,如網絡訪問,文件訪問,數據庫訪問以及在UI線程上運行的那些處理。因爲處理限制UI的響應時間會很長,因爲它不會爲UI組件提供處理機會。

我希望你明白爲什麼你現在會得到這樣的例外。長時間運行的操作不應限制UI線程操作。所以它應該從UI線程移動到另一個新線程(移動代碼創建HttpClient,直到您收到來自它的響應)。 Android也爲此提供了另一種選擇。您可以創建一個AsyncTask,它爲您處理線程創建過程。你可以寫你的代碼並將結果傳遞給UI線程。詳細瞭解它。

注意:所有線程都訪問進程內存。但是一個進程不能訪問另一個進程的內存,除非它擁有相同的用戶ID。除非它來自您的應用程序之一。這可以使用AIDL接口完成。

我希望這個解決方案能幫助你理解你得到的異常並解決它們。

+0

如果你想創建一個線程或AsyncTask,那麼我可以給它一個例子。 –

+0

感謝您的信息 –