2015-05-24 52 views
9

我有一個從View擴展類,我試圖用這個代碼試圖執行最後一行時調用popupwindow的showAtLocation崩潰的應用程序

public class dbView extends View implements View.OnTouchListener { 

    private void showDialog(String msg) { 
     LayoutInflater layoutInflater; 
     View dialogContent; 
     final PopupWindow popupWindow; 

     layoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     dialogContent = layoutInflater.inflate(R.layout.pop_up_dialog, null); 

     popupWindow = new PopupWindow(
       dialogContent, 
       ViewGroup.LayoutParams.WRAP_CONTENT, 
       ViewGroup.LayoutParams.WRAP_CONTENT); 

     popupWindow.showAtLocation(this, Gravity.CENTER, 10, 10); 

    } 

} 

我的應用程序崩潰,顯示一個popupWindow。異常的消息是

無法創建內螺紋)處理器已經不叫 Looper.prepare(

我一直在尋求與該消息的答案,他們都涉及到彈出窗口正在單獨的線程上創建,我應該使用 runOnUIThread但如果我在查看我需要這個嗎?造成這個問題的原因是什麼?

+0

你說過,有一個錯誤,如「不能創建處理程序內部線程沒有調用Looper.prepare()」,但你在哪裏提到關於使用「處理程序」的代碼。請用你完成的代碼解釋我的意思,所以我可以爲你嘗試。 –

回答

3

這取決於你在哪裏打電話showDialog(String msg),我知道你是從你的View類調用它,但這並不意味着它在UI線程上,View調用在UI線程上處理,但是如果你在一個線程中進行View調用,你將會有這個錯誤。我知道相同的代碼解決了它自己,但是如果你在View類中運行TimerTask或線程,你應該仔細檢查它們。而不是runOnUithread,你可以在你的View類中調用post(runnable);(同樣的機制Handler),這將確保可運行調用將被髮送到主線程。

總之檢查要在清單

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> 

稱其爲您View

+0

如果一個TimerTask從顯示對話框的視圖中調用一個方法怎麼辦?我是否必須在該調用中使用RunUiThread? –

+0

是的,你有一個'TimerTask'運行不同的Thread-(它創建一個新的線程),所以即使你在一個View中調用你的方法,它應該是在UI線程上,但它不是......做你讓我先生?如果你想移動到你的View類的UI線程中,使用post方法,它和''Handler'一樣,在我的回答中@ MauricioGracia – Elltz

1

我想這可能是因爲您試圖干擾您的用戶界面從非原始線程(創建用戶界面)。您的自定義視圖類無法更改用戶界面,因此我認爲最好的方法是致電runOnUIThread()。雖然我聽說使用runOnUIThread可能不是最好的選擇,但在我看來,這將是你的情況所需要的。

平時要得到這個工作,我作出這樣的擴展應用(在我的情況下,它ContextGetter)的特殊類並實現這樣的方法:

public class ContextGetter extends Application { 

    private static Context context; 

    public void onCreate(){ 
     super.onCreate(); 
     context = getApplicationContext(); 
    } 

    public static Context getAppContext() { 
     return context; 
    } 
} 

它幫助我從任何地方獲取應用程序上下文。您還應該將其添加到您的清單中,如下所示:

<application 
     android:name=".ContextGetter" 
     android:allowBackup="true" 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" 
     android:theme="@style/AppTheme" > 

幷包括您在此標記內的所有活動。

當你有你的背景,你可以做這件事情:

((Activity)ContextGetter.getAppContext()).runOnUiThread(new Runnable() 
{ 
//doSomethingInside 
}); 

它可能看起來很奇怪,但它必須爲你工作。它看起來是這樣,因爲Activity來自Context。每當你嘗試它,我想知道它是否工作。希望我幫助的問題

+0

我從同一視圖調用這個! –

+0

你能否給我提供一個具體的例子 –

+0

不管你是否願意,這只是一個提供賞金的問題,現在使用和我發佈的代碼一樣的代碼現在正在工作! –

1

您可以通過窗口管理器製作自己的固定它。

private void showCustomPopupMenu() 
{ 
      windowManager2 = (WindowManager)getSystemService(WINDOW_SERVICE); 
      LayoutInflater layoutInflater=(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      View view=layoutInflater.inflate(R.layout.xxact_copy_popupmenu, null); 
      params=new WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT, 
        WindowManager.LayoutParams.WRAP_CONTENT, 
        WindowManager.LayoutParams.TYPE_PHONE, 
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, 
        PixelFormat.TRANSLUCENT); 

      params.gravity=Gravity.CENTER|Gravity.CENTER; 
      params.x=10; 
      params.y=10; 
      windowManager2.addView(view, params); 
}