AlertDialog не может быть показан из ListActivity в ActivityGroup - PullRequest
4 голосов
/ 05 февраля 2011

Я пытаюсь показать AlertDialog при нажатии элемента в ListActivity. Мое приложение отображает ListActivity на вкладке TabActivity, и AlertDialog не показывает никаких проблем. ListActivity (называемая FavouritesActivity) в значительной степени прямо из документов Android, с этим параметром:

    lv.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {

                //... code to set the strings station, number, route, and direction

                FavouritesActivity.this.confirmSend(position);
            }
        });

, а затем

public void confirmSend(final int position) {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage("Are you sure?")
        .setCancelable(true)
        .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    //... some code to run here                                                              
                }
            })
        .setNegativeButton("No", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
                }
            });
    AlertDialog alert = builder.create();
    alert.show();
}

Однако на второй вкладке TabActivity у меня есть группа ActivityGroup, которая использует LocalActivityManager для запуска другой ListActivity, например, так (опять же, почти без изменений из учебника по спискам вложения во вкладках онлайн):

public class MyGroupActivity extends ActivityGroup {

// Keep this in a static variable to make it accessible for all the nesten activities, lets them manipulate the view                                      
public static MyGroupActivity group;

// Need to keep track of the history if you want the back-button to work properly, don't use this if your activities requires a lot of memory.            
private ArrayList<View> history;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.history = new ArrayList<View>();
    group = this;

    // Start the root activity withing the group and get its view                                                                                         
    View view = getLocalActivityManager().startActivity("FirstListActivity", new
                                                        Intent(this,FirstListActivity.class)
                                                        .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
        .getDecorView();

    // Replace the view of this ActivityGroup                                                                                                             
    replaceView(view);

}

public void replaceView(View v) {
    // Changes this Groups View to the new View.                                                                                                          
    setContentView(v);
}

FirstListActivity здесь - это ListActivity, которое является первым в серии. Пользователь выбирает элемент и ему предоставляется другая ListActivity с кодом, подобным этому:

    lv.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {
                Intent intent = new Intent();
                intent.setClass(FirstListActivity.this, TheNextListActivity.class);                                                                                                                

                // Create View using the Group Activity's LocalActivityManager                                                                            
                View newview = MyGroupActivity.group.getLocalActivityManager()
                    .startActivity("show_routes", intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
                    .getDecorView();
                // And replace the view                                                                                                                   
                MyGroupActivity.group.replaceView(newview);
            }
        });

Последний ListActivity в этой серии имеет ТОЧНО такой же прослушиватель onItemClick и связанную с ним функцию verifySend, что и первый показанный мной пример ListActivity (тот, который работает), но теперь, когда пользователь нажимает на элемент, AlertDialog не отображается приложение неожиданно останавливается с этим отладочным выводом:

W/WindowManager(  570): Attempted to add application window with unknown token android.os.BinderProxy@4373af30.  Aborting.
D/AndroidRuntime( 1953): Shutting down VM
W/dalvikvm( 1953): threadid=3: thread exiting with uncaught exception (group=0x4000fe70)
E/AndroidRuntime( 1953): Uncaught handler: thread main exiting due to uncaught exception
E/AndroidRuntime( 1953): android.view.WindowManager$BadTokenException: Unable to add window -- token android.app.LocalActivityManager$LocalActivityRecord@43750f98 is not valid; is your activity running?
E/AndroidRuntime( 1953):    at android.view.ViewRoot.setView(ViewRoot.java:425)
E/AndroidRuntime( 1953):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:178)
E/AndroidRuntime( 1953):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
E/AndroidRuntime( 1953):    at android.view.Window$LocalWindowManager.addView(Window.java:392)
E/AndroidRuntime( 1953):    at android.app.Dialog.show(Dialog.java:231)
E/AndroidRuntime( 1953):    at com.ttcsms.LastListActivity.confirmSend(LastListActivity.java:119)
E/AndroidRuntime( 1953):    at com.ttcsms.LastListActivity$1.onItemClick(LastListActivity.java:66)
E/AndroidRuntime( 1953):    at android.widget.AdapterView.performItemClick(AdapterView.java:283)
E/AndroidRuntime( 1953):    at android.widget.ListView.performItemClick(ListView.java:3132)
E/AndroidRuntime( 1953):    at android.widget.AbsListView$PerformClick.run(AbsListView.java:1620)
E/AndroidRuntime( 1953):    at android.os.Handler.handleCallback(Handler.java:587)
E/AndroidRuntime( 1953):    at android.os.Handler.dispatchMessage(Handler.java:92)
E/AndroidRuntime( 1953):    at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime( 1953):    at android.app.ActivityThread.main(ActivityThread.java:3948)
E/AndroidRuntime( 1953):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 1953):    at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime( 1953):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:782)
E/AndroidRuntime( 1953):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:540)
E/AndroidRuntime( 1953):    at dalvik.system.NativeStart.main(Native Method)
I/Process (  570): Sending signal. PID: 1953 SIG: 3
I/dalvikvm( 1953): threadid=7: reacting to signal 3
I/dalvikvm( 1953): Wrote stack trace to '/data/anr/traces.txt'
I/Process ( 1953): Sending signal. PID: 1953 SIG: 9
I/ActivityManager(  570): Process com.ttcsms (pid 1953) has died.

В чем разница между этими двумя маршрутами к AlertDialog, которые вызывают этот сбой? Кажется, это как-то связано с битом AlertDialog.Building (this). Когда внутри ActivityGroup, он получает неправильный контекст или что-то. Каждый найденный в Интернете пример этой ошибки был решен путем переключения между «this» и «getApplicationContext ()», но в этом случае ни один из этих способов не работает. Я пробовал другие варианты получения контекста, но, как я догадывался в основном наугад, я подумал, что лучше спросить здесь совета. Какой контекст я должен передавать или что еще не так?

Ответы [ 4 ]

21 голосов
/ 05 февраля 2011

Понял! На самом деле это проблема Android Context .

В строке:

AlertDialog.Builder builder = новый AlertDialog.Builder ( this );

Вместо этого вы должны передать контекст TabActivity , контекст видимого / основного действия передается для отображения любого всплывающего окна внутри действия.

Итак, простое решение:

  1. Сохранить контекст TabActivity для последующего использования во всплывающем окне.
  2. Передайте контекст TabActivity во всплывающем коде вместо этого.

надеюсь, это поможет. ура :) 1027 *

5 голосов
/ 01 ноября 2011

Чтобы сделать это довольно просто, вместо определения переменной контекста и установки ее на onCreate, вы можете просто передать getParent() в качестве контекста в AlertDialog.

5 голосов
/ 08 июня 2011

Наконец последовал твой подход и решил мою проблему.Здесь я даю некоторые подробности

создать контекст для класса Tabactivity следующим образом.

"открытый статический контекст MyTabactivity;"

assgin "context = this" в методе onCreate MyTabactivity.
Затем используйте MyTabactivity.context в своих окнах оповещений следующим образом.

"AlertDialog.Builder adb = new AlertDialog.Builder (MyTabactivity.context);"

Надеюсь, это поможет .....

1 голос
/ 08 июня 2011

Я просто хочу присоединиться и сказать, что приведенный выше ответ не работает для меня надежно (когда я возобновляю все приложение, я вижу тот же старый сбой).Что работало, так это использование родительского контекста.См. Также:

как отобразить предупреждение в группе действий?

...