5

我需要从处理线程制作 Android Toast,这是 OpenCV 自定义的,所以我不能按照此处的建议使用 runOnUiThread(): Android: Toast in a thread

大部分代码来自 CVCamera 示例应用程序。但是那些不熟悉的,当我选择 Surf 菜单按钮时,SURFProcessor 是这样调用的:

           else if (item.getTitle().equals("SURF")) {

                   defaultcallbackstack.addFirst(new SURFProcessor());
                   toasts(DIALOG_TUTORIAL_SURF, "");

           }

运行此处理器线程,以便当我按下手机的相机按钮 (capturePress = true) 时,会拍摄图像并完成处理。我想调用 toasts 方法,如图所示:

class SURFProcessor implements NativeProcessor.PoolCallback {

           @Override
           public void process(int idx, image_pool pool, long timestamp,
                           NativeProcessor nativeProcessor) {
                   if(capturePress) {
                           String processMsg = processor.processFeatures(idx, pool, cvcamera.DETECT_SURF);
                           capturePress = false;
                           toasts(PROCESS_MESSAGE, processMsg);
                   }
           }
}

这是 toasts 方法,位于扩展 Activity 的主类中:

void toasts(int id, String msg) {
           switch (id) {
           case PROCESS_MESSAGE:
                   Toast.makeText(MMRapp.this, msg, Toast.LENGTH_LONG).show();
                   break;
.........

现在这段代码给了我一个错误:“不能在没有调用 Looper.prepare() 的线程内创建处理程序。” 我该如何调用 toasts 方法?或者是否可以让 toasts 方法监听 processMsg 的变化?如果可能的话,我可以通过发送 processMsg 或更改类变量来代替。本质上,我需要从这个处理器线程更新一个字符串。

非常感谢,如果需要,我会提供更多信息/代码。
-汤姆

4

3 回答 3

6

使用 handler 和 runnable 使 Handler 和 runnable 在活动中:

// these are members in the Activity class
Handler toastHandler = new Handler();
Runnable toastRunnable = new Runnable() {public void run() {Toast.makeText(Activity.this,...).show();}}

然后从你的线程调用它使用

toastHandler.post(toastRunnable);

处理程序在创建它的线程中执行 runnable。

于 2011-03-22T02:09:14.647 回答
1

使用适合您需要的过载。

/**
 * Muestra un toast sin necesidad de preocuparse de estar en el hilo de la
 * UI o no.
 *
 * @param mContext
 * @param sMessage
 */
public static void showToast(final Context mContext, final int nMessageId) {
    if (Utils.isUiThread()) {
        Toast.makeText(mContext.getApplicationContext(), nMessageId, Toast.LENGTH_LONG).show();
        return;
    }
    Runnable mRunnableToast = new Runnable() {
        @Override
        public void run() {
            Toast.makeText(mContext.getApplicationContext(), nMessageId, Toast.LENGTH_LONG).show();
        }
    };
    if (mContext instanceof Activity) {
        ((Activity) mContext).runOnUiThread(mRunnableToast);
        return;
    }
    Utils.runOnUiThread(mRunnableToast);
}

/**
 * Muestra un toast sin necesidad de preocuparse de estar en el hilo de la
 * UI o no.
 *
 * @param mContext
 * @param sMessage
 */
public static void showToast(final Context mContext, final CharSequence sMessage) {
    if (Utils.isUiThread()) {
        Toast.makeText(mContext.getApplicationContext(), sMessage, Toast.LENGTH_LONG).show();
        return;
    }
    Runnable mRunnableToast = new Runnable() {
        @Override
        public void run() {
            Toast.makeText(mContext.getApplicationContext(), sMessage, Toast.LENGTH_LONG).show();
        }
    };
    if (mContext instanceof Activity) {
        ((Activity) mContext).runOnUiThread(mRunnableToast);
        return;
    }
    Utils.runOnUiThread(mRunnableToast);
}

public static boolean isUiThread() {
    Looper mCurrentLooper = Looper.myLooper();
    if (mCurrentLooper == null) {
        return false;
    }
    if (mCurrentLooper.equals(Looper.getMainLooper())) {
        return true;
    }
    return false;
}

public static void runOnUiThread(Runnable mRunnable, Context mContext) {
    if (mContext instanceof Activity) {
        runOnUiThread(mRunnable, (Activity) mContext);
    } else {
        Utils.runOnUiThread(mRunnable);
    }
}

public static void runOnUiThread(Runnable mRunnable, View vView) {
    if (Utils.isUiThread()) {
        mRunnable.run();
    } else {
        vView.post(mRunnable);
    }
}

public static void runOnUiThread(Runnable mRunnable, Activity mActivity) {
    if (mActivity != null) {
        mActivity.runOnUiThread(mRunnable);
    } else {
        Utils.runOnUiThread(mRunnable);
    }
}

public static void runOnUiThread(Runnable mRunnable) {
    if (Utils.isUiThread()) {
        mRunnable.run();
    } else {
        Handler mUiHandler = new Handler(Looper.getMainLooper());
        mUiHandler.post(mRunnable);
    }
}
于 2016-07-06T10:59:26.850 回答
0

为什么不简单地使用广播接收器?
写下来

public class ToastTrigger extends BroadcastReceiver {

    public static final String EXTRA_MESSAGE = "message";

    @Override
    public void onReceive(Context context, Intent intent) {
        Timber.d("ToastTrigger: received");
        if (intent.hasExtra(EXTRA_MESSAGE)) {
            Toast.makeText(context, intent.getStringExtra(EXTRA_MESSAGE), Toast.LENGTH_SHORT)
                .show();
        }
    }
}

定义它

    <receiver
        android:name=".receivers.ToastTrigger"
        android:enabled="true"
        android:exported="false">
        <intent-filter>
            <action android:name="com.example.TOAST" />
        </intent-filter>
    </receiver>

触发它

public void showMessage(String message) {
    Intent intent = new Intent();
    intent.setAction(getPackageName() + ".TOAST");
    intent.putExtra(ToastTrigger.EXTRA_MESSAGE, message);
    sendBroadcast(intent);
}
于 2018-01-01T12:08:41.633 回答