2016-10-17 4 views
1

я получил следующий кусок кода:по расписанию Таймер блокировки себя

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); 

Он должен проверить наличие QR-кода в TextureView четыре раза в секунду. Расчет занимает немного меньше одной секунды. Проблема в том, что таймер открывает только один поток, который блокирует себя => Задача запускается только один раз в секунду.

Согласно this комментарий scheduleAtFixedRate должен сделать трюк ... Но это не так, он ведет себя точно так же, как schedule в моей ситуации.

Что было бы лучшим вариантом для достижения того, что я хочу?

EDIT: Я заменил таймер на ScheduledExecutorService, как это предложено в комментариях, но это все равно приводит к точному поведению.

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); 
+0

Попробуйте использовать AsyncTask проверить QR-код в фоновом режиме. –

+0

Попробуйте заменить таймер на ScheduledExecutorService. Это работает для меня правильно –

+0

@HareshChhelana '' 'textureView.getBitmap()' '' необходимо вызывать из потока пользовательского интерфейса. Я не могу получить его растровое изображение из потока AsyncTask. – Benni

ответ

0

Возможное решение будет для задачи таймера для запуска нового потока, чтобы выполнить проверку, так что до тех пор, как новый запуск нити не принимает более 0,25 секунды, что бы быть в состоянии идти в ногу.

Проблема в том, что фактическая проверка будет перекрываться, что означает, что у вас может быть 3-4 задания, которые одновременно находят QR-код. То есть то, что вы хотите, поскольку это может иметь проблемы параллелизма дальше по линии.

+0

... это не проблема, потому что хотя результаты немного задерживаются, я все еще получайте мои результаты четыре раза в секунду, чего я хочу достичь. – Benni

0

Вы хотите проверить QR-код в фоновом потоке и обновить ui, тогда вы должны использовать фоновый поток и обработчик для обновления пользовательского интерфейса. Это можно сделать несколькими способами. это один из способов.

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); 
       } 
      }); 

    } 
    } 

Вы также можете использовать AsyncTask или наблюдателя картина механизм также

+0

Извините за поздний ответ. Это делает то же самое, что и мое решение, так как оно не сканирует изображение до тех пор, пока предыдущее сканирование не будет завершено. ('' 'backgroundHandler.postDelayed''' вызывается после того, как предыдущее сканирование завершено. Я попытался поместить его в начало, которое до сих пор не имеет никакого эффекта.) – Benni

+0

да, потому что вы что-то сканируете непрерывно (быстрее и быстрее, сканирование в миллисекундах), так почему вы даете 250 мс времени. вы можете попробовать с 20 мс tim, тогда это может быть полезно. Вышеупомянутый код вызывает только после 250 мс. –

+0

Я хочу запустить сканирование каждые 250 мс, независимо от того, запущен ли еще один процесс сканирования или нет. Что делает ваш код, так это дождаться завершения сканирования, подождите 250 мс и снова запустите сканирование. Если сканирование занимает 1000 мс, у меня есть задержка не 250, а 1250 мс, что является огромной разницей. Даже если бы я сделал '' 'backgroundHandler.postDelayed (это, 0);' '', он имел бы 1000 мс + 0мс = 1000 мс, а не 250 мс. – Benni

Смежные вопросы