【问题标题】:Where to "quit" with looper?Looper 在哪里“退出”?
【发布时间】:2013-07-11 03:53:56
【问题描述】:

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

想法?

【问题讨论】:

    标签: android android-asynctask exit looper


    【解决方案1】:

    有两种情况需要考虑:

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

    QuotingGoogle 工程师,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() 发送给处理程序

    【讨论】:

    • 除非你想关闭并生成一个新的类似线程:“你的线程永远不会退出——它将保留在 Looper.loop() 中,因为你从未告诉它退出循环。”
    【解决方案2】:

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

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

    【讨论】:

    • 谢谢你的回答,但如果我不写 loope.prepae() 我有一个错误
    • 在没有Looper.prepare() 的情况下出现错误表明您正在执行一个任务,该任务需要doInBackground 线程上的消息队列 - 即 Looper - 但我看不到哪个部分您的代码需要Looper。与AsyncTask 一起使用的后台线程不打算有消息队列。后台执行最好使用HandlerThread
    猜你喜欢
    • 2011-02-17
    • 1970-01-01
    • 1970-01-01
    • 2017-06-14
    • 2013-07-30
    • 2016-02-21
    • 1970-01-01
    • 1970-01-01
    • 2021-07-22
    相关资源
    最近更新 更多