简体   繁体   中英

Scheduled Timer blocking itself

I've got following piece of code:

Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        TextureView textureView = (TextureView) findViewById(R.id.texture);

        if (textureView != null) {
            try {
                Log.i("MainActivity", "Read start");
                String str = readQr(textureView.getBitmap());
                if (str != null)
                    Log.i("MainActivity", str);
                else Log.i("MainActivity", "No QR Code found.");
            } catch (NotFoundException ex) {
                Log.i("MainActivity", "No QR Code found.");
            } catch (ChecksumException | FormatException e) {
                e.printStackTrace();
            }
        }
    }
}, 0, 250);

It should check for a QR code in the TextureView four times a second. The calculation takes a bit less than one second. The problem is, that the timer opens only one thread, which blocks itself => The task gets run only around one time a second.

According to this comment scheduleAtFixedRate should do the trick... But it does not, it behaves exactly like schedule in my situation.

What would be the best option to achieve what I want?

EDIT: I replaced the Timer by a ScheduledExecutorService , as suggested in the comments, but it still results in the exactly same behaviour.

ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10); // I know it's too much, I just tried using 10 Threads because 4 did still not work.
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        final TextureView textureView = (TextureView) findViewById(R.id.texture);

     if (textureView != null) {
            try {
                Log.i("MainActivity", "Read start");
                String str = readQr(textureView.getBitmap());
                if (str != null)
                    Log.i("MainActivity", str);
                else Log.i("MainActivity", "No QR Code found.");
                Log.i("MainActivity", "Read end");
            } catch (NotFoundException ex) {
                Log.i("MainActivity", "No QR Code found.");
                Log.i("MainActivity", "Read end");
            } catch (ChecksumException | FormatException e) {
                e.printStackTrace();
                Log.i("MainActivity", "Read end");
            }
        }
    }
}, 0, 250, TimeUnit.MILLISECONDS);

A possible solution would be for the timer task to launch a new thread to perform the check, so as long as the new thread launch doesnt take more than 0.25 seconds it would be able to keep up.

The problem is that the actual check is going to overlap, meaning that you may have 3-4 tasks all finding the QR code at the same time. So is that what you want as it may have concurrency issues further down the line.

You want to check the QR code in the background thread and update the ui, then you should use background thread and Handler for updating the UI. It can be done in number of ways. this is one way.

 public class FifthActivity extends AppCompatActivity  {

       Handler uiHandler;
        Handler backgroundHandler;
        TextView textureView;
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.collapsing_layout);
        textureView = (TextView) findViewById(R.id.textView_fifth);



            uiHandler=new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);

                    textureView.setText(msg.getData().getString("msg"));

                }
            };
            HandlerThread thread=new HandlerThread("BackgroundTask");
            thread.start();
            backgroundHandler=new Handler(thread.getLooper());


           backgroundHandler.post(new Runnable() {
                @Override
                public void run() {

                    Log.i("FifthActivity", "Read start");
                    String str = ""+ new Random().nextInt(10);
                    if (str != null) {
                        Log.i("FifthActivity", str);
                        Message message=uiHandler.obtainMessage();
                        Bundle bundle=new Bundle();
                        bundle.putString("msg",str);
                        message.setData(bundle);
                        uiHandler.sendMessage(message);
                       // textureView.setText(str);
                    }
                    else Log.i("FifthActivity", "No QR Code found.");
    backgroundHandler.postDelayed(this,250);
                }
            });

    }
    }

You can also use asynctask or Observer pattern Mechanism also

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM