2013-06-08 2 views
0

활동을 대화 상자로 사용합니다 (문제는 생각하지 않지만 언급합니다).onClick 및 AsyncTask 치명적인 예외 # 1

Dialog가 사용자로부터 일부 데이터를 가져온 다음 Apache's HttpClient을 사용하여 해당 데이터를 웹 서비스에 보냅니다. 즉, 해당 Button과 연결된 onClick() 메서드와 Button이 있습니다. onClick()이 발생하면 사용자가 추가 한 데이터를 얻고이를 JSON으로 보내는 메서드 (sendJSON)에 전달합니다.

그럼 스레드에 대한 코드를 추가했습니다. AsyncTask를 매개 변수로 사용하여 데이터를 전달하고 doInBackgroundsendJSON 메서드를 호출하고 이제는 onClick 내에서 사용자 데이터를 매개 변수로 사용하여 execute()을 호출하기 만하면됩니다.

Google에서 검색 한 내용에서 내 활동에 대한 호출을하므로 sendJSON 메서드를 호출 할 수 있습니다. 그리고는 이것이다 :

Do not access the Android UI toolkit from outside the UI thread 

그래서 나는 두 가지 질문을 얻었다. 이 문제의 신속한 해결 방법은 무엇입니까? onClick() 메서드 내부에 runOnUiThread이 작업을 수행합니까? 그리고 두 번째로 내 논리가 처음부터 잘못 되었습니까? 필자가 필요로하는 메서드를 작성한 다음 스레드에 대한 코드를 추가했습니다. 그래서 내가 처음부터 어떻게 생각 했어야 했습니까?

코드를 작성하고 잘못된 것을 이해하기 위해 검색하는 데 많은 시간이 걸렸으므로 그로부터 배워야 할 내용을 알고 싶습니다. 동일한 오류를 다시 반복하지 마십시오.

감사합니다

편집 : 코드

온 클릭 :

@Override 
public void onClick(View v) { 

     if(v == send) { 


      //Mocking data 
      String network="anetwork", password , comment; 
      String lat="1", longt="2"; 

      EditText passwd = (EditText)findViewById(R.id.password); 
      password = passwd.getText().toString(); 

      EditText com = (EditText)findViewById(R.id.comment); 
      comment = com.getText().toString(); 


      LongSend ls = new LongSend(); 
      ls.execute(lat,longt,network,password,comment); 

     } 
    } 

AsyncTask를 :

public class LongSend extends AsyncTask<String, Void, Void> { 

    @Override 
    protected Void doInBackground(String... params){ 
     Log.i("AsyncTask", "here 1"); 

     int param1 = Integer.parseInt(params[0]); 
     int param2 = Integer.parseInt(params[1]); 

     DialogActivity da = new DialogActivity(); 
     try { 
      da.sendJson(param1, param2, params[2], params[3], params[4]); 
     } catch (JSONException e) { 
      e.printStackTrace(); 
     }   

     return null; 
    } 


    @Override 
    protected void onPreExecute() { 

    } 


    @Override 
    protected void onPostExecute(Void nothing) { 
     //    
    } 

} 

sendJSON

public void sendJson(int lat, int longt, String network, String passwd, String comment) throws JSONException { 

    HttpClient httpclient = new DefaultHttpClient(); 
    HttpPost httppost = new HttpPost("web_service_here"); 
    HttpResponse response; 

    JSONObject json = new JSONObject(); 
    JSONObject nested = new JSONObject(); 

     try { 
       Log.i("SENDJSON", " print"); 

       nested.put("lat", lat); 
       nested.put("longt", longt); 

       json.put("coord", nested);  //add "nested" to "json" 

       json.put("network", network); 
       json.put("password", passwd); 
       json.put("comment", comment); 

       StringEntity se = new StringEntity(json.toString()); 
       se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json")); 

       httppost.getParams().setParameter("json", json); 

       Log.v("sendJSON", "json== " +json); 

       httppost.setEntity(se); 
       Log.v("sendJSON", "SE== " +se); 

       response = httpclient.execute(httppost); 

       if(response !=null) { 

         str = inputStreamToString(response.getEntity().getContent()).toString(); 

         Log.i("POST", "send JSON data"); 
         Log.i("DATA", "Data Send==" +str); 

       } 

     } catch (ClientProtocolException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 


} 

활동

public class DialogActivity extends Activity implements OnClickListener { 

public static String str; 
Button send; 

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


    send = (Button)findViewById(R.id.button_send); 
    send.setOnClickListener(this); 


} 

로그 캣 :

06-08 05 : 33 : 59.801 : E/AndroidRuntime (397) FATAL EXCEPTION : AsyncTask를

1 06-08 05 : 33 : 59.801 : E/AndroidRuntime (397)는 java.lang.RuntimeException가 :

doInBackground()를

실행 중 오류가 발생 06-08 05 : 33 : 59.801 : E/AndroidRuntime (397) android.os.AsyncTask $ 3.done에서 (AsyncTask를. java : 266) 06-08 05 : 33 : 59.801 : E/AndroidRuntime (397) : 에서 java.util.concurrent.FutureTask $ Sync.innerSetException (FutureTask.java:273) 06-08 05:33:59 .801 : E/AndroidRuntime (397) : at java.util.concurrent.FutureTask.setException (FutureTask.java:124) 06-08 05 : 33 : 59.801 : E/AndroidRuntime (397) : java.util. 동시. FutureTask $ Sync.innerRun (FutureTask.java:307) 06-08 05 : 33 : 59.801 : E/AndroidRuntime (397) : java.util.concurrent.FutureTask.run (FutureTask.java:137) 06 -08 05 : 33 : 59.801 : E/AndroidRuntime (397) : 에서 java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1081) 06-08 05 : 33 : 59.801 : E/AndroidRuntime (397) : 에서 java.util.concurrent.ThreadPoolExecutor $ Worker.run (ThreadPoolExecutor.java:574) 06-08 05 : 33 : 59.801 : E/AndroidRuntime (397) : 에서 java.lang.Thread.run (Thread. 자바 : 1020) 06-08 05 : 33 : 59.801 : E/AndroidRuntime (397) : 원인 : java.lang.RuntimeException : Looper.prepare()를 호출하지 않은 스레드에서 핸들러를 만들 수 없음 06-08 05 : 33 : 59.801 : E/AndroidRuntime (397) : android.os.Handler. (Handler.java:121) 06-08 05 : 33 : 59.801 : E/AndroidRuntime (397) : android.app.Activity (Activity.java:727) 06-08 05 : 33 : 59.801 : E/AndroidRuntime (397) : 에서 org.teo.wifit.DialogActivity. (DialogActivity.java:30) 06-08 05:33 : 59.801 : E/AndroidRuntime (397) : at org.teo.wifit.DialogActivity $ LongSend.doInBackground (DialogActivity.java:88) 06-08 05 : 33 : 59.801 : E/AndroidRuntime (397) : org. teo.wifit.Dialog 활동 $ LongSend.doInBackground (DialogActivity.java:1) 06-08 05 : 33 : 59.801 : E/AndroidRuntime (397) : android.os.AsyncTask $ 2.call (AsyncTask.java:252) 06-08 05 : 33 : 59.801 : E/AndroidRuntime (397) : 에서 java.util.concurrent.FutureTask $ Sync.innerRun (FutureTask.java:305) 06-08 05 : 33 : 59.801 : E/AndroidRuntime (397) : ... 4 문제는

라인 (88) 더 여기서 DialogActivity da = new DialogActivity();

+1

코드를 입력하십시오. – amrinder007

+0

@ amrinder007 코드 및 Logcat 추가 – mt0s

+0

@Raghunandan 완료. – mt0s

답변

1

확인 & 읽기 안드로이드 developper guide

Android UI 툴킷이 thread-safe이 아니라고 알려줍니다. 따라서, 단일 스레드 모델은 UI가 동시에 다른 스레드에 의해 수정되지 않습니다 보장 :

앱을 구현할 하지 않는 한, 이 단일 스레드 모델은 성능 저하를 얻을 수있는 사용자 상호 작용에 응답하여 집중적 인 작업을 수행 귀하의 응용 프로그램을 제대로. 특히 UI 스레드에서 모든 것이 일 경우 네트워크 과 같은 긴 작업을 수행하거나 데이터베이스 쿼리가 전체 UI를 차단합니다. 스레드가 으로 차단되면 그리기 이벤트를 포함하여 이벤트를 전달할 수 없습니다. 사용자의 관점에서 에서 응용 프로그램이 중단 된 것처럼 보입니다. 심지어 악화, UI 스레드가 몇 초 이상 차단되면 (약 5 초) 사용자에게 악의적 인 "응답 없음 (ANR)"대화 상자가 표시됩니다. 그런 다음 사용자가 을 선택하여 응용 프로그램을 종료하고 불만이라면 제거하십시오.

또한 Andoid UI 툴킷은 스레드로부터 안전하지 않습니다. 따라서 작업자 스레드에서 UI를 조작하지 않아야합니다. UI 스레드에서 사용자 인터페이스로 조작을 모두 수행해야합니다.

1

당신은에서/액세스 UI를 업데이트 할 수 없습니다 UI 스레드 외부 에서 안드로이드 UI 툴킷에 액세스하지 마십시오 UI 스레드를 차단하지 마십시오

: 따라서,이 는 안드로이드의 단일 스레드 모델이 규칙은 단순히 doInBackground(). ui 스레드에서 ui를 업데이트/액세스해야합니다. runOnUithread를 사용할 수 있습니다.

http://developer.android.com/reference/android/os/AsyncTask.html

확인 위의 링크

에서 문서 당신은 doInBackground (PARAMS)에서 모든 네트워크 관련 작업을 할 수 있습니다. doInBackground (params) 계산의 결과는 onPostExecute (result)의 매개 변수입니다.

doInBackground는 백그라운드 스레드에서 호출됩니다. 결과를 반환하고 결과에 따라 u를 업데이트하거나 onPostExecute에서 대화 상자 또는 메시지를 표시 할 수 있습니다.

+0

네, 그건 사실입니다. 제 질문에서도 언급했습니다. 그래서'runOnUiThread'는 제가 할 수있는 최선의 해결책입니다, 아니면'AsyncTask'를 사용할 수 있도록 코드에서 약간의 변경을 할 수 있습니까? – mt0s

+1

@ mt0s 새로운 Dialogactivity를 만들 필요가 없습니다. doinbackground에서 http 작업을 수행하십시오. 부울 값을 반환합니다. 부울 값에 따라 onPostExecute()에 메시지 또는 대화 상자를 표시 할 수 있습니다. – Raghunandan

0

백그라운드 스레드에서 UI 관련 작업을 수행 할 수 없으므로 표시 또는 수정과 같은 모든 UI 관련 작업이 주 스레드에서 수행되어야합니다. 따라서 이러한 작업을 수행하려면 ActivityName.this.runOnUIThread() 메서드를 사용하거나 onPostExecute에서 UI 작업을 수행하십시오.

관련 문제