我需要从处理线程制作一个Android吐司,这是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或改变类变量来实现。本质上,我需要从此处理器线程更新的字符串。
非常感谢,如果需要,我会提供更多信息/代码 - 汤姆
答案 0 :(得分:6)
使用处理程序和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。
答案 1 :(得分: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);
}
}
答案 2 :(得分: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);
}