Where to “quit” with looper?

五迷三道 提交于 2020-01-12 09:45:08

问题


I have a problem with a looper. I call looper.prepare(), and after doing something it all works fine. But if I rotate the device I get an exception on the prepare.

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

I'm trying to quit the looper, but it doesn't do anything.

Here is my 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();
       }

Ideas?


回答1:


There are two cases to consider:

(1) looper threads you want to live the entire life of the app, and do not hold strong reference to a view (even not implicitly)

Quoting Google engineer, Christopher Tate - you can just leave the looper there until your app is destroyed, and it will go down with it. You don't need to worry about it.

"Speaking very generally, never quit() your looper threads. That method exists mostly for historical and testing reasons. In Real Life™, I recommend that you continue to reuse the same looper thread(s) for the life of the process rather than creating/quitting them."

I use such a looper thread as a multi purpose HandlerThread, and send Runnables to it whenever I want something to run outside the main thread (UI).

(2) looper threads that have reference to a view

This one falls out of the recommendation of Christopher Tate, because it will cause memory leak, for example if you rotate the screen.
(You better make the handler thread static and use weak reference - and you'll be back with option #1)
To kill it you must quit the loop. To do that, you need to run the quit command on the context of that thread.
So create a message with some whatever int as your msg.what, and in your handleMessage wait for this int, and when it arrives - call:

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

And don't forget to null all reference to views and activities.

Send this kill message to the handler from your activity onDestroy()




回答2:


Looper.prepare() associates a Looper-instance with the thread that it is called on, but Looper.quit() does not remove this association (it merely stops the message dispatch mechanism). So, when you get a second call to Looper.prepare a RuntimeException is thrown.

The general recommendation is to not associate Looper-instances with AsyncTask-threads. The Looper is intended for passing messages between threads, but this is already handled internally in the AsyncTask, so that data can be sent between onPreExecute (UI thread) -> doInBackground (Worker thread) -> onPostExecute (UI thread).



来源:https://stackoverflow.com/questions/17617731/where-to-quit-with-looper

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!