调用popupwindow的showAtLocation会导致应用程序崩溃

时间:2015-05-24 14:31:19

标签: android popup

我的课程从View延伸,我试图使用此代码显示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 中,我需要这个吗?造成这个问题的原因是什么?

3 个答案:

答案 0 :(得分:4)

这取决于你在哪里调用showDialog(String msg),我知道你是从你的View类调用它,但这并不意味着它在UI线程上,View调用是在UI线程上处理的,但如果你在线程中进行View调用,您将遇到该错误。我知道相同的代码解决了自己,但如果你在View类中运行TimerTask或Threads,你应该仔细检查它们。而且runOnUithread代替post(runnable);,您可以在View类中调用Handler(相同的机制View),这将确保将runnable调用发送到主线程。

简而言之,请在 var uri = 'http://www.com.test/my/download/url'; Ext.DomHelper.append(Ext.getBody(), { tag: 'iframe', id: 'iframe-export', frameBorder: 0, width: 0, height: 0, css: 'display:none;visibility:hidden;height:0px;', src: uri }); 班级

中查看您在哪里调用它

答案 1 :(得分:1)

我认为这可能是因为您试图从非原始线程(创建UI)干扰您的UI。您的自定义视图类无法更改UI,因此我认为最好的方法是调用runOnUIThread()。虽然我听说使用runOnUIThread可能不是最佳选择,但在我看来,这正是您所需要的。

通常为了实现这个目的,我创建了一个扩展Application的特殊类(在我的例子中是它的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。无论何时尝试,我都想知道它是否有效。希望我帮助解决了这个问题

答案 2 :(得分: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);  
}