Eli*_*iss 5 multithreading flutter
我正在尝试使用以下包在 flutter 中使用 Tesseract https://github.com/arrrrny/tesseract_ocr
\n\n我已经下载了应用程序并运行。
\n\n问题是extractTextUI 挂起。
查看Java代码:
\n\n Thread t = new Thread(new Runnable() {\n public void run() {\n baseApi.setImage(tempFile);\n recognizedText[0] = baseApi.getUTF8Text();\n baseApi.end();\n }\n });\n t.start();\n try { t.join(); } catch (InterruptedException e) { e.printStackTrace(); }\n result.success(recognizedText[0]);\nRun Code Online (Sandbox Code Playgroud)\n\n我可以看到它正在一个新线程上运行,所以我希望它不会挂起应用程序,但它仍然如此。
\n\n我找到了这个例子:
\n\n new Handler(Looper.getMainLooper()).post(new Runnable() {\n @Override\n public void run() {\n // Call the desired channel message here.\n baseApi.setImage(tempFile);\n recognizedText[0] = baseApi.getHOCRText(0);\n baseApi.end();\n result.success(recognizedText[0]);\n\n }\n });\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n但它也会挂起 UI。
\n\n文档还说
\n\n**Channels and Platform Threading**\nInvoke all channel methods on the platform\xe2\x80\x99s main thread when writing code on the platform side.\nRun Code Online (Sandbox Code Playgroud)\n\n有人可以澄清这句话吗?
\n\n根据Richard Heap答案,我尝试从本机调用方法到 dart,传递结果:
省道面:
\n\n_channel.setMethodCallHandler((call) {\n print(call);\n switch (call.method) {\n case "extractTextResult":\n final String result = call.arguments;\n print(result);\n }\n var t;\n return t;\n});\nRun Code Online (Sandbox Code Playgroud)\n\nJava端:
\n\n通道.invokeMethod("extractTextResult","hello");
\n\n如果我从主线程调用这个方法,这工作正常,但线程会阻塞。
\n\n如果我做
\n\n Thread t = new Thread(new Runnable() {\n public void run() {\n channel.invokeMethod("extractTextResult","test1231231");\n\n }\n });\n t.start();\n\n result.success("tst"); // return immediately\nRun Code Online (Sandbox Code Playgroud)\n\n然后应用程序崩溃并显示以下消息:
\n\n\n\n我也尝试过:
\n\n Thread t = new Thread(new Runnable() {\n public void run() {\n new Handler(Looper.getMainLooper()).post(new Runnable() {\n @Override\n public void run() {\n // Call the desired channel message here.\n baseApi.setImage(tempFile);\n recognizedText[0] = baseApi.getHOCRText(0);\n baseApi.end();\n result.success(recognizedText[0]);\n // channel.invokeMethod("extractTextResult", "test1231231");\n }\n });\n\n }\n });\n t.start();\n\n result.success("tst");\nRun Code Online (Sandbox Code Playgroud)\n\n这就是我理解Richard Heap最后一条评论的意思,但它仍然挂起用户界面。
小智 5
我遇到了同样的问题,并使用 TesseractOcrPlugin.java 中的 MethodCallWrapper 修复了它
此代码适用于我(不需要更改 Dart 代码):
package io.paratoner.tesseract_ocr;
import com.googlecode.tesseract.android.TessBaseAPI;
import android.os.Handler;
import android.os.Looper;
import android.os.AsyncTask;
import java.io.File;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;
/** TesseractOcrPlugin */
public class TesseractOcrPlugin implements MethodCallHandler {
private static final int DEFAULT_PAGE_SEG_MODE = TessBaseAPI.PageSegMode.PSM_SINGLE_BLOCK;
/** Plugin registration. */
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "tesseract_ocr");
channel.setMethodCallHandler(new TesseractOcrPlugin());
}
// MethodChannel.Result wrapper that responds on the platform thread.
private static class MethodResultWrapper implements Result {
private Result methodResult;
private Handler handler;
MethodResultWrapper(Result result) {
methodResult = result;
handler = new Handler(Looper.getMainLooper());
}
@Override
public void success(final Object result) {
handler.post(new Runnable() {
@Override
public void run() {
methodResult.success(result);
}
});
}
@Override
public void error(final String errorCode, final String errorMessage, final Object errorDetails) {
handler.post(new Runnable() {
@Override
public void run() {
methodResult.error(errorCode, errorMessage, errorDetails);
}
});
}
@Override
public void notImplemented() {
handler.post(new Runnable() {
@Override
public void run() {
methodResult.notImplemented();
}
});
}
}
@Override
public void onMethodCall(MethodCall call, Result rawResult) {
Result result = new MethodResultWrapper(rawResult);
if (call.method.equals("extractText")) {
final String tessDataPath = call.argument("tessData");
final String imagePath = call.argument("imagePath");
String DEFAULT_LANGUAGE = "eng";
if (call.argument("language") != null) {
DEFAULT_LANGUAGE = call.argument("language");
}
calculateResult(tessDataPath, imagePath, DEFAULT_LANGUAGE, result);
} else {
result.notImplemented();
}
}
private void calculateResult(final String tessDataPath, final String imagePath, final String language,
final Result result) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
final String[] recognizedText = new String[1];
final TessBaseAPI baseApi = new TessBaseAPI();
baseApi.init(tessDataPath, language);
final File tempFile = new File(imagePath);
baseApi.setPageSegMode(DEFAULT_PAGE_SEG_MODE);
baseApi.setImage(tempFile);
recognizedText[0] = baseApi.getUTF8Text();
baseApi.end();
result.success(recognizedText[0]);
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}.execute();
}
}
Run Code Online (Sandbox Code Playgroud)
通过使用,join您可以让主线程等待后台线程,并阻止它。您必须删除连接并立即返回结果。
那么,如何返回ocr结果呢?这个结果不会立即可用。当它可用时,您可以从 Native 调用一个方法到 dart,并传递结果。在 dart 结束时,您可以将结果作为任何异步事件进行处理。
你的问题最后一段的要点是你的结果将在你的后台线程上可用,所以你想在那里调用原生的 dart 方法。你不能。您必须将方法调用代码发布到主循环程序 - 您已经显示了一些用于发布到主循环程序的代码,您可以将其用作示例。
| 归档时间: |
|
| 查看次数: |
5312 次 |
| 最近记录: |