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.