0

I created a Looper thread class:

public class MyLooperThread extends Thread{
    private Handler mHandler;

    public void init(){
         start(); //start the thread

         synchronized (this) {
            wait(5000); //wait for run()
         }
         Log.d("DEBUG","Init Done!");

         //EXCEPTION: Can't create handler inside thread that has not called Looper.prepare()
         MyObject obj = new MyObject(mHandler);
   }

    @Override
    public void run() {
        Looper.prepare();

        mHandler = new Handler(){
           @Override
           public void handleMessage(Message msg){
            //Check installed app package names, NOTHING RELATED WITH UI                ...
            }
        };
        synchronized (this) {
            notify(); 
        }
        Looper.loop();

     }//end of run()
}

In my Activity, I call above MyLooperThread 's init() method in onCreate(). Besides, I have a ToggleButton element, when ToggleButton is checked, I call MyLooperThread's init() method too.

public class MyActivity extends Activity implements OnCheckedChangeListener{
   …
   @Override
   protected void onCreate(Bundle savedInstanceState){
      …
      myToggleButton.setOnCheckedChangeListener(this);
      myToggleButton.setChecked(true);//checked by default

      MyLooperThread myLooper = new MyLooperThread();
      myLooper.init();

   }

   @Override
   public void onCheckedChanged(CompoundButton button, boolean isChecked) {
    if(isChecked){
          MyLooperThread myLooper = new MyLooperThread();
          myLooper.init();
      }else{
          ...
      }
    }
}

When launch my app, it is fine. My toggle button is shown as checked by default. When I uncheck it & check it again, I got exception:

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

which is pointed to the init() method's last line of code MyObject obj = new MyObject(mHandler);

Why I got this exception? I don't understand, my mHandler is created after I called Looper.prepare() in run().

Mellon
  • 37,586
  • 78
  • 186
  • 264

3 Answers3

1

Pretty sure the error is saying you're trying to do something UI related when not on the UI thread.

K5 User
  • 606
  • 1
  • 6
  • 10
  • THanks for the hint, but I am not able to find where am I wrong with this hint – Mellon Oct 04 '13 at 14:56
  • 1
    What's HandleMessage() doing ? The error you're getting means the thread is trying to do something UI (toast, etc) but is not the UI thread. Thus the error. Google the error, the sidebar is full of similar problems, all related to doing UI work on a non-UI thread. – K5 User Oct 04 '13 at 15:02
  • my handleMessage() method isn't doing anything with UI, it simply check the installed app package names – Mellon Oct 04 '13 at 19:54
0

As you haven't posted anything that you're doing inside the handleMessage, I'm gonna assume that you're trying to change one of the UI elements. Always use the UI thread to update the UI. It should go something like this:

handleMessage(Message msg) {
    ...
    getActivity().runOnUiThread(new Runnable {
        ...
        // update UI here
        ...
    });
    ...
}
Ashray Mehta
  • 375
  • 1
  • 7
  • my handleMessage() method isn't doing anything with UI, it simply check the installed app package names – Mellon Oct 04 '13 at 19:56
  • Are you sure none of the UI objects are touched in handleMessage()? A toast is made or a dialog is modified, perhaps? Also, could you post the code inside handleMessage()? – Ashray Mehta Oct 05 '13 at 08:03
0

just use a HandlerThread():

ht = new HandlerThread();
ht.start();
h = new Handler(ht.getLooper());
pskink
  • 23,874
  • 6
  • 66
  • 77