2015-05-24 2 views
9

У меня есть класс, который простирается от View, и я пытаюсь показать popupWindow с помощью этого кодавызова showAtLocation из popupwindow происходит сбой приложения

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

    } 

} 

Мое приложение сбой при попытке выполнить эту последнюю строку. Сообщение исключения является

Невозможно создать обработчик внутри потока, который не под названием Looper.prepare()

Я искал ответы, связанные с этим сообщением и все они подразумевают, что всплывающее окно создавалось на отдельной ветке и что я должен использовать runOnUIThread, но если я вхожу в VIEW, мне нужно это сделать? Что может быть причиной этой проблемы?

+0

вы сказали, имея ошибку «Невозможно создать обработчик внутри потока, который не называется Looper.prepare()», но где вы упоминаете код об использовании «Handler». пожалуйста, объясните мне правильно с вашим готовым кодом, чтобы я мог попробовать. –

ответ

3

Это зависит от того, где вы звоните showDialog(String msg), я знаю, что вы вызывали его из класса View, но это не значит, что он находится в потоке пользовательского интерфейса, просмотр вызовов обрабатывается в потоке пользовательского интерфейса, но если вы сделаете вызов View в потоке, вы получите эту ошибку. Я знаю, что тот же самый код решил сам, но если вы запускаете TimerTask или Threads в классе View, вам следует их дважды проверить. А также вместо runOnUithread вы можете позвонить post(runnable); (тот же механизм Handler) в свой класс View, который будет проверять, что вызов runnable будет отправлен в Основной поток.

В короткой проверки, где вы называете его в View классе

+0

Что делать, если TimerTask вызывает метод из представления, отображающего диалог, мне нужно использовать RunUiThread для этого вызова? –

+0

Да, у вас есть, поскольку 'TimerTask' запускает другой Thread- (он создает новый поток), поэтому, даже если вы вызываете свои методы в представлении, которые должны быть в потоке пользовательского интерфейса, это не ... do вы получаете меня сэр? если вы хотите перейти к теме пользовательского интерфейса в классе View, используйте метод 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

манифеста

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

вы можете установил ее, сделав свой собственный через оконный менеджер.

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); 
} 
Смежные вопросы