5

我有一个活套问题。我打电话looper.prepare(),做某事后一切正常。但是,如果我旋转设备,我会在准备时遇到异常。

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

我试图退出looper,但它什么也没做。

这是我的异步任务:

 @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();
       }

想法?

4

2 回答 2

16

有两种情况需要考虑:

(1) Looper 线程你希望在应用程序的整个生命周期中都存在,并且不持有对视图的强引用(甚至不是隐含的)

引用Google 工程师 Christopher Tate 的话——你可以把 looper 留在那里,直到你的应用程序被销毁,它会随之消失。你不必担心它。

“非常笼统地说,永远不要退出()你的活套线程。该方法的存在主要是出于历史和测试原因。在 Real Life™ 中,我建议您在进程的生命周期内继续重用相同的活套线程,而不是创建/退出它们。”

我将这样的循环线程用作多用途HandlerThread,并在我希望某些东西在主线程 (UI) 之外运行时将 Runnables 发送给它。

(2) 引用视图的looper线程

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

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

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

将此终止消息从您的活动发送到处理程序onDestroy()

于 2013-11-22T00:05:06.800 回答
4

Looper.prepare()Looper-instance 与调用它的线程相关联,但Looper.quit()不会删除此关联(它只是停止消息分发机制)。因此,当您第二次调用Looper.preparea时,RuntimeException就会抛出异常。

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

于 2013-07-14T04:29:20.193 回答