0

Hi im trying to do an app that searchs bluetooth devices that are near every 5-10 seconds, so I tried to do an endless loop but the app is getting stuck when I press the button that starts the loop:

int stopInt=2;
serachB.setOnClickListener(
            new Button.OnClickListener() {
                public void onClick(View v) {
                    do {
                        final Handler handler = new Handler();
                        handler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                listAdapter.clear();
                                getPairedDevices();
                                startDiscovery();

                            }
                        }, 4000);

                    } while (stopInt>1);
                }
Admond
  • 13
  • 4
  • 1
    What do you mean with "the app is getting stuck"? As in, an endless loop? Sounds like what you're attempting – CubeJockey Jul 06 '16 at 14:17
  • 3
    You should decrement the stopInt variable in some place. Until it will result in infinite loop – Shriram Jul 06 '16 at 14:17
  • CubeJockey- it freezes up and after a while get terminated, Shriram- can you please give me an example, I didn't understand – Admond Jul 06 '16 at 14:22
  • 1
    "How to create an unresponsive App." You shot yourself in the foot by looping infinitely on the GUI-Thread. Just start some recurring scheduling in the onClick. See https://developer.android.com/training/articles/perf-anr.html and for example https://guides.codepath.com/android/Repeating-Periodic-Tasks and http://stackoverflow.com/a/14377875/982149 – Fildor Jul 06 '16 at 14:34
  • `while (stopInt>1);` end less loop, stopInt is always > 1 – Shank Jul 06 '16 at 15:34

3 Answers3

1
private final Handler mMyhandler = new Handler();

private final Runnable checkBluetoothRunnable = new Runnable() {
    public void run() {

        //Do your work here

        mMyHandler.postDelayed(this, 5000);
    }

};

serachB.setOnClickListener(
    new Button.OnClickListener() {
        public void onClick(View v){
          mMyhandler.post(checkBluetoothRunnable);
        }
    }
}
yongsunCN
  • 736
  • 7
  • 18
0

Change it this way:

serachB.setOnClickListener(
    new Button.OnClickListener() {
        public void onClick(View v) {
            final Handler handler = new Handler();
            handler.post(new Runnable() {
                @Override
                public void run() {
                    while(true){
                        listAdapter.clear();
                        getPairedDevices();
                        startDiscovery();
                        Thread.sleep(4000);
                    }
                } 
            });
        }}
user6547359
  • 204
  • 1
  • 9
0

You are continually creating new instances of Handler in your while loop which is going to eat up memory. I wouldn't be surprised if you were getting an OutOfMemoryError which is causing the termination. Try creating a single instance outside of your loop.

The Runnable passed to Handler runs on the UIThread since it was created on that thread. This should be avoided for lengthy operations and instead delegated to another thread.

When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it

Also, rather than using the Handler class you could potentially swap it out to use ScheduledThreadPoolExecutor which will give you a pool of threads which can then periodically execute your device discovery code.

Firstly create a ScheduledExecutorService:

ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

Create an instance of your Runnable:

MyRunnable deviceDiscovery = new MyRunnable();

Then in your onClick method you kick off with scheduleAtFixedRate:

ScheduledFuture<?> future = scheduledExecutorService.scheduleAtFixedRate(deviceDiscovery, 0, 1, TimeUnit.MINUTES);

Then when you want to stop it running you need to call cancel on the ScheduledFuture:

future.cancel(true); // Set to true to say it can interrupt if already running
kstandell
  • 775
  • 6
  • 16