在哪里与looper“退出”?

时间:2013-07-12 14:49:52

标签: android android-asynctask exit looper

我有一个looper的问题。我打电话给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();
       }

想法?

2 个答案:

答案 0 :(得分:16)

有两种情况需要考虑:

(1)你想要在应用程序的整个生命周期中生活的looper线程,并且不要强烈引用视图(甚至不是隐含的)

Quoting Google工程师Christopher Tate - 您可以将looper留在那里,直到您的应用程序被销毁,并且它会随之崩溃。你不必担心它。

  

“非常普遍地说,永远不要退出()你的looper线程。这种方法主要是出于历史和测试的原因。在Real Life™中,我建议你继续重复使用相同的looper线程。过程而不是创建/退出它们。“

我使用这样一个looper线程作为多用途HandlerThread,并且只要我想在主线程(UI)之外运行某些东西,就将Runnables发送给它。

(2)引用视图的looper线程

这个不符合Christopher Tate的建议,因为它会导致内存泄漏,例如,如果您旋转屏幕。
(你最好使处理程序线程静态并使用弱引用 - 你将返回选项#1)
要杀死它你必须退出循环。为此,您需要在该线程的上下文中运行quit命令 所以用msg.what创建一个带有一些int的消息,并在handleMessage中等待这个int,当它到达时 - 调用:

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

不要忘记取消对视图和活动的所有引用。

将此杀戮信息从您的活动onDestroy()

发送给处理程序

答案 1 :(得分:3)

Looper.prepare()Looper - 实例与调用它的线程相关联,但Looper.quit()不会删除此关联(它只会停止消息调度机制)。因此,当您再次拨打Looper.prepare时,会抛出RuntimeException

一般建议不要将Looper - 实例与AsyncTask - 主题相关联。 Looper用于在线程之间传递消息,但这已在AsyncTask内部处理,因此可以在onPreExecute(UI线程) - >之间发送数据。 doInBackground(工作人员主题) - > onPostExecute(UI线程)。