扫码后调用initLoader报错:必须在主线程调用该方法
解决
initLoader must be called on the main thread异常 嘿,我一眼就看出问题所在了——你是在后台线程里调用initLoader了!
问题根源
BarcodeDetector的Processor.receiveDetections()方法是在后台线程运行的,而Android的Loader框架有严格的线程要求:initLoader必须在主线程(UI线程)中调用。所以你直接在这里触发realizarConsulta(),自然就抛出了线程违规的异常。
快速修复方案
只需要把调用realizarConsulta的逻辑切换到主线程执行就行,Android的Activity自带runOnUiThread()方法可以帮你搞定这个:
修改你的Procesador类里的receiveDetections方法:
@Override public void receiveDetections(Detector.Detections<Barcode> detections) { SparseArray<Barcode> objetosDetectados = detections.getDetectedItems(); if(objetosDetectados.size() > 0) { Barcode barcode = objetosDetectados.valueAt(0); EscaneoActivity.codigoActual = barcode; Bundle b = new Bundle(); b.putLong(ConsultorProductosBD.X, Long.parseLong(barcode.displayValue)); // 关键:切换到主线程执行查询 escaneoActivity.runOnUiThread(new Runnable() { @Override public void run() { escaneoActivity.realizarConsulta(b); } }); } }
为什么你之前的尝试没解决问题?
你之前把操作移到Activity的成员方法里,但问题的核心不是方法在哪里,而是调用这个方法的线程不对。receiveDetections是BarcodeDetector在后台线程触发的,所以哪怕调用的是Activity的方法,执行环境还是后台线程,必须显式切换到主线程才能安全调用initLoader。
简化写法(可选)
如果你的项目支持Java 8及以上,用Lambda表达式可以让代码更简洁:
escaneoActivity.runOnUiThread(() -> escaneoActivity.realizarConsulta(b));
这样看起来清爽多了~
内容的提问来源于stack exchange,提问作者JuanDavid
相关产品推荐
相关产品推荐

