2011-03-22 2 views
5

OpenCV 용 사용자 정의 처리 스레드 인 안드로이드 토스트를 만들어야하므로 여기에 제안 된대로 runOnUiThread()를 사용할 수 없습니다. Android: Toast in a thread.다른 스레드에서 토스트 만드는 법 (sans runOnUiThread)

이 코드의 대부분은 CVCamera 샘플 앱에서 가져온 것입니다. 나는 서핑 메뉴 버튼을 선택하면하지만 그 낯선이의 SURFProcessor은과 같이 호출됩니다

나는 휴대 전화의 카메라 버튼을 누를 때 (= 사실 capturePress), 이미지가 촬영되도록이 프로세서 쓰레드가 실행
  else if (item.getTitle().equals("SURF")) { 

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

      } 

처리가 완료되었습니다. 같이 나는 토스트 메소드를 호출 할 :

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

지금이 코드는 나에게 오류를 제공합니다 :

여기
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); 
        } 
      } 
} 

는 메인 클래스에있는 토스트 방법, 확장 활동이다 "할 수 없습니다 Looper.prepare()를 호출하지 않은 스레드 내부에서 핸들러를 생성하십시오. " 토스트 방법을 호출하는 방법에 대해 어떻게 생각합니까? 또는 토스트 메서드에서 processMsg의 변경 내용을 수신 할 수 있습니까? 가능한 경우 processMsg를 보내거나 클래스 변수를 변경하여 처리 할 수 ​​있습니다. 본질적으로,이 프로세서 스레드에서 업데이트 된 String이 필요합니다.

대단히 감사합니다. 원하는 경우 추가 정보/코드를 제공해 드리겠습니다.

toastHandler.post(toastRunnable); 

핸들러가를 실행 스레드의 사용에서 그것을 호출 한 후

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

:

답변

6

사용 핸들러와 실행 가능한 은 활동의 핸들러 및 실행 가능합니다 생성 된 스레드에서 실행 가능

+0

는 감사가

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

트리거 정의! 매력처럼 작동합니다 ... 나는 그것을 할 수있는 간단한 방법이 있어야한다고 생각했습니다. – wrapperapps

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); 
    } 
} 
+0

이 질문과 대답을 읽는 다른 사람들을 위해이 문제가 어떻게 해결되는지 더 구체적으로 알려주십시오. 원래 포스터가 요청한 경우이 중 어느 것을 사용해야합니까? –

+1

음, 꽤 간단합니다. OP의 문제는 그가 UI 스레드 외부의 토스트를 게시하려고 시도하고 있으며 허용되지 않는다는 것입니다. 내 스 니펫이이를 처리합니다. 자신의 코드 (BroadcastReceiver 컨텍스트, 활동, 응용 프로그램 등)에서 액세스 할 수있는 개체에 따라 그는 하나 또는 다른 과부하를 사용할 수 있습니다. 아마도 이것은 하나의 :'public static void showToast (최종 문맥 mContext, 최종 CharSequence sMessage)' – Reaper

+0

이 정교화는 매우 유용합니다. 이것에 대해 확장 해 주셔서 감사합니다! –

0

브로드 캐스트 reveiver를 사용하지 않는 이유는 무엇입니까?
쓰기는

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(); 
     } 
    } 
} 

public void showMessage(String message) { 
    Intent intent = new Intent(); 
    intent.setAction(getPackageName() + ".TOAST"); 
    intent.putExtra(ToastTrigger.EXTRA_MESSAGE, message); 
    sendBroadcast(intent); 
} 
관련 문제