«android.util.AndroidRuntimeException: requestFeature () должен быть вызван перед добавлением содержимого» в showDialog (dialogId) - PullRequest
8 голосов
/ 28 января 2011

Этот выводит меня на грань безумия!

У меня есть действие, в котором я инициализирую представление Button с помощью onClickListener, например:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.myLayout);

    mMyButton = (Button) findViewById(R.id.myButtonId);
    mMyButton.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            showDialog(ID_MYDIALOG);
        }
    });
}

Я также написалмой собственный класс конструктора диалогов (одноэлементный), так как в моем приложении есть несколько других Activity, которые будут использовать общий набор диалогов, следовательно, в функции onCreateDialog(int id) для данного Activity я вызываю:

@Override
protected Dialog onCreateDialog(int id) {
    Dialog dialog;

    switch (id) {
        case ID_MYDIALOG:
            dialog = DialogBuilder.getInstance().getMyDialog(this, mUri, mListener);
            break;

        default:
            dialog = null;
            break;
    }

    return dialog;
}

Переменные mUri и mListener определены в другом месте, и я убедился, что они действительны.Соответствующие части класса singleton DialogBuilder выглядят так:

public AlertDialog getMyDialog(Context context, Uri uri, DialogInterface.OnClickListener listener) {
    // Inflate the custom body for the AlertDialog.
    LayoutInflater layoutInflater = LayoutInflater.from(context);
    View view = layoutInflater.inflate(R.layout.myDialogBody, null);

    // Get the data to show in the dialog.
    Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
    cursor.moveToFirst();

    // Create a suitable data adapter and use it to populate the dialog body with data.
    MyDialogDataAdapter adapter = new MyDialogDataAdapter(context, cursor);

    // Populate the GridView in the dialog body with data.
    GridView grid = (GridView) view.findViewById(R.id.myDialogDataGrid);
    grid.setAdapter(adapter);

    return new AlertDialog.Builder(context)
    .setIcon(R.drawable.myDialogIcon)
    .setTitle(R.string.myDialogTitle)
    .setView(view)
    .setPositiveButton(R.string.myDialogDone, listener)
    .create();
}

Теперь, когда я запускаю свое приложение и нажимаю кнопку (то есть mMyButton), я получаю следующую трассировку стека исключений:

E/AndroidRuntime( 1247): FATAL EXCEPTION: main
E/AndroidRuntime( 1247): android.util.AndroidRuntimeException: requestFeature() must be called before adding content
E/AndroidRuntime( 1247):    at com.android.internal.policy.impl.PhoneWindow.requestFeature(PhoneWindow.java:181)
E/AndroidRuntime( 1247):    at com.android.internal.app.AlertController.installContent(AlertController.java:203)
E/AndroidRuntime( 1247):    at android.app.AlertDialog.onCreate(AlertDialog.java:251)
E/AndroidRuntime( 1247):    at android.app.Dialog.dispatchOnCreate(Dialog.java:307)
E/AndroidRuntime( 1247):    at android.app.Activity.createDialog(Activity.java:886)
E/AndroidRuntime( 1247):    at android.app.Activity.showDialog(Activity.java:2557)
E/AndroidRuntime( 1247):    at android.app.Activity.showDialog(Activity.java:2524)
E/AndroidRuntime( 1247):    at com.dbm.myApp.myActivity$4.onClick(myActivity.java:266)
E/AndroidRuntime( 1247):    at android.view.View.performClick(View.java:2534)
E/AndroidRuntime( 1247):    at android.view.View$PerformClick.run(View.java:9210)
E/AndroidRuntime( 1247):    at android.os.Handler.handleCallback(Handler.java:587)
E/AndroidRuntime( 1247):    at android.os.Handler.dispatchMessage(Handler.java:92)
E/AndroidRuntime( 1247):    at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime( 1247):    at android.app.ActivityThread.main(ActivityThread.java:3652)
E/AndroidRuntime( 1247):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 1247):    at java.lang.reflect.Method.invoke(Method.java:507)
E/AndroidRuntime( 1247):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
E/AndroidRuntime( 1247):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
E/AndroidRuntime( 1247):    at dalvik.system.NativeStart.main(Native Method)
W/ActivityManager(  212):   Force finishing activity com.dbm.myApp/.myActivity

Если я правильно интерпретирую трассировку стека, проблема возникает в тот самый момент, когда я нажимаю на свою кнопку (по состоянию на com.dbm.myApp.myActivity$4.onClick(myActivity.java:266), которая является точной showDialog(ID_MYDIALOG); строкой).

Что вы, коллеги-разработчики Android, говорите?Что, по вашему мнению, вызывает мою проблему?

Справедливо предположить, что приведенный выше код действителен в соответствии с компиляцией, модульными тестами и т. Д. Однако данный код упрощен и разбит, чтобы соответствоватьпожалуйста, не пытайтесь комментировать соглашения об именах и т. д.

Ответы [ 3 ]

17 голосов
/ 28 января 2011

Я думаю, что мог бы решить проблему: если я по какой-то причине создаю AlertDialog с:

return new AlertDialog.Builder(context)
    .setIcon(R.drawable.myDialogIcon)
    .setTitle(R.string.myDialogTitle)
    .setView(view)
    .setPositiveButton(R.string.myDialogDone, listener)
    .show();

т.е. с .show(); вместо .create(); Проблема больше не присутствует. Я не знаю, почему это работает или чем отличается функция AlertDialog.Builder::show() от функции AlertDialog.Builder::create(); (больше, чем очевидная разница, отраженная в соответствующих именах функций).

3 голосов
/ 28 января 2011

Попробуйте вызвать .setView(view) сразу после конструктора.

return new AlertDialog.Builder(context)
    .setView(view)
    .setIcon(R.drawable.myDialogIcon)
    .setTitle(R.string.myDialogTitle)
    .setPositiveButton(R.string.myDialogDone, listener)
    .create();

Помогает ли это?

1 голос
/ 28 января 2011

Это может быть не решение .. но я был немного удивлен этой частью:

mMyButton.setOnClickListener(new View.OnClickListener() {
    showDialog(ID_MYDIALOG);

Я думал, что вы должны реализовать onClick внутри слушателя?я не прав?

...