2013-07-12 35 views
2

我有一個活套問題。我打電話looper.prepare(),並做了一些事情後,一切正常。但是如果我旋轉設備,我會在準備中遇到異常情況。從哪裏「彎腰」?

07-12 16:40:09.760: E/activity(15809): java.lang.RuntimeException: Only one Looper may be created per thread 

我想退出活套,但它什麼也沒做。

這裏是我的AsyncTask:

@Override 
    protected String doInBackground(String... args) { 

     try{Looper.prepare(); //here start the exception 

     try { 

      URL url = new URL(link); 
      HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 
     conn.setDoInput(true); 
      conn.connect(); 
      InputStream is = conn.getInputStream(); 
      utente.measure(0, 0); 
      bmImg = decodeSampledBitmapFromResource(is,(int) utente.getMeasuredWidth(), utente.getMeasuredHeight(), link); 

if(bmImg!=null){ 


     try{ 

     getCroppedBitmap(); 
     }catch(Exception e){ 
      System.out.println(e); 
     } 

      } 

     } 
     catch (IOException e) 
     {  
      Log.e("lele", "errore qui"); 
      e.printStackTrace(); 

     } 
     Looper.myLooper().quit(); //do nothings 
     }catch(Exception e){ 
      Log.e("canta tu", " "+e); 
     } 
     Looper.myLooper().quit(); //do nothings 
     return null; 
    } 
     @Override  
protected void onPostExecute(String args) { 

      //Looper.myLooper().quit(); //generathed an error, main thread can't stop looper 

     if(bmImg!=null){ 
      try{ 

      utente.setImageBitmap(bmImg); 
      ellisse.setVisibility(View.VISIBLE); 

      }catch(Exception e){ 
       Log.e("lele",""+e); 
       Log.e("lele","errore probabile out of bound"); 
      } 

      } 
     else { 

      Toast.makeText(getApplicationContext(), "Modifica la foto da \"profilo\"", Toast.LENGTH_LONG).show(); 
     } 

想法?

回答

13

有兩種情況考慮:

(1)環線你想住在應用程序的整個生命,不要到一個視圖持有強引用(甚至沒有隱含的)

Quoting谷歌工程師克里斯托弗泰特 - 你可以留下這個looper直到你的應用程序被銷燬,並且它會隨着它下去。你不需要擔心它。

「概而言之,從沒有放棄過()的環線。這個方法大多存在歷史和測試的原因。在現實生活中™,我建議你繼續重複使用相同的彎針線(個),這個過程的生命,而不是創造/退出它們。「

我用這樣的彎針線爲多用途HandlerThread,併發送的Runnable到它,每當我想要的東西向主線程(UI)之外運行。

(2)具有參照視圖

這一次掉下來克里斯托弗·泰特的建議,因爲它會導致內存泄漏,例如,如果您旋轉屏幕環線。
(您最好使處理程序線程靜態並使用弱引用 - 並且您將返回選項#1)
要殺死它,您必須退出循環。爲此,您需要在該線程的上下文中運行quit命令。
因此,創建一個消息的一些什麼INT爲您msg.what,並在你的handleMessage等待這個中斷,並且當它到達 - 撥打:

Looper myLooper = Looper.myLooper(); 
if (myLooper!=null) { 
    myLooper.quit(); 
} 

而且不要忘記爲空的所有參考的意見和活動。

從您的活動發送殺消息的處理程序onDestroy()

+0

除非你想關閉併產生一個新的類似線程: 「你的線程永遠不會退出 - 它將保留在Looper.loop()中,因爲你從未告訴它退出循環。」 – JohnyTex

2

Looper.prepare()同夥一Looper -instance與線程,它被稱爲,但Looper.quit()不會刪除這個協會(它只是停止消息調度機制)。所以,當你第二次打電話給Looper.prepare時,會拋出一個RuntimeException

一般建議不要將Looper -orders與AsyncTask -threads聯繫起來。 Looper用於在線程之間傳遞消息,但這已在AsyncTask的內部處理過,因此可以在onPreExecute(UI線程) - >doInBackground(工作線程) - >onPostExecute(UI線程)之間發送數據。

+0

感謝對你的答案,但如果我不寫loope.prepae()我有,你得到一個錯誤,而不'尺蠖錯誤 – Lele

+0

.prepare()'表示你正在執行一個需要'doInBackground'線程上的消息隊列的任務 - 也就是一個Looper - 但是我看不到需要'Looper'的代碼部分。與'AsyncTask'一起使用的後臺線程不打算有一個消息隊列。爲後臺執行使用'HandlerThread'會更好。 – AndersGoransson