Android Wieso geht getApplicationContext() bei Toast, aber nicht bei AlertDialog.Builder?

Windows10

Bekanntes Mitglied
Ich habe über MainActivity eine weitere Activity über ein Intent gestartet.
Java:
Intent intent=new Intent(this, NewFilmActivity.class);

startActivityForResult(intent, 1);
Dieser Code funktioniert.

Wenn ich in dieser Activity jetzt aber folgede zwei Sachen mit einem AlertDilaog.Builder ausführe, klappt es nicht.
Java:
 private AlertDialog.Builder showAlertDialog(String s, String neutral)
    {
       return new AlertDialog.Builder(this)
                .setCancelable(false)
                .setIcon(android.R.drawable.ic_dialog_info)
                .setMessage(s)
                .setNeutralButton(neutral, null);
    }
oder
Java:
 private AlertDialog.Builder showAlertDialog(String s, String neutral)
    {
       return new AlertDialog.Builder(getApplicationContext())
                .setCancelable(false)
                .setIcon(android.R.drawable.ic_dialog_info)
                .setMessage(s)
                .setNeutralButton(neutral, null);
    }

Bei Toast würde es aber klappen

Java:
Toast.makeText(getApplicationContext(), "Hallo", Toast.LENGTH_LONG).show();
Also wieso klappt getApplicationContext() bei Toast schon aber bei AlertDialog.Builder nicht?
 
Kannst Du noch Details nennen, was für einen Fehler du bekommst? Fehler / Exception mit Stacktrace und so können immer bei der Fehlersuche weiter helfen.
 
Kann es aber schon auf das beschriebene Problem oben beschränken (AlertDialog.Builder), da der Fehler immer im Zusammenhang mit dem AlertDialog.Builder auftritt.
 

Anhänge

  • 1591639947986.png
    1591639947986.png
    326,1 KB · Aufrufe: 15
Bitte sowas nicht als Bildschirmfoto sondern in Code Tags posten. Dann ist es deutlich besser.

Und dann zeig mal den Code, wann Du das überhaupt aufrufst? Kann es sein, dass die Activity schon beendet wurde, wenn Du das aufrufst? Das wäre dann eine Erklärung für diese Exception (siehe z.B. https://stackoverflow.com/questions/2850573/activity-has-leaked-window-that-was-originally-added) Beachte die Erläuterungen dazu: Die Activity könnte z.B. durch eine Exception schon beendet worden sein z.b. in einem Async Task oder so!

Also bitte bring mehr: Das was Du hier bringst ist aus meiner Sicht für eine Fehlersuche nicht ausreichend.
 
Der gesamte Code der Klasse mit dem Fehler:
Java:
package htl.grieskirchen.pos.android.filmapp;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;

import java.util.concurrent.ExecutionException;

public class NewFilmActivity extends AppCompatActivity {
    private Spinner status;
    private Button anlegen;
    private EditText title;
    private Film film;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_new_film);
        this.status=findViewById(R.id.spinnerNewStatus);
        this.anlegen=findViewById(R.id.anlegenSuchen);
        this.title=findViewById(R.id.editFilm);
        Status[]statuses=Status.values();
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, toStringArray(statuses));
        this.status.setAdapter(adapter);
        this.anlegen.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               getFilm(v);
               Intent data = new Intent();
               data.putExtra("title", film.getName());
               data.putExtra("status", film.getStatus().toString());
               setResult(RESULT_OK, data);
               finish();
               }
        });
    }

    private String[] toStringArray(Status[] statuses) {
        String[]s=new String[statuses.length];
        for(int i=0;i<statuses.length;i++)
        {
            if(statuses[i]==Status.NICHTS)
            {
                s[i]=" ";
            }
            else {
                s[i] = statuses[i].toString();
            }
        }
        return s;
    }

    private void getFilm(View v)
    {
        String filmname=this.title.getText().toString();
        sucheFilm(filmname);
        if(film==null)
        {
            newFilmAnlegen(filmname);
            AlertDialog.Builder builder=showAlertDialog("Neuer Film wurde erfolgreich angelegt", "ok");
            builder.show();
        }
    }
    private void newFilmAnlegen(String s)
    {
        if(s.equals(""))
        {
            AlertDialog.Builder builder=showAlertDialog("Es wurde kein Film eingegeben! Hole es nach!  ", "ok");
            builder.show();
        }
        else if(this.status.getSelectedItem().toString().equals(""))
        {
            film=new Film(s);
        }
        else
        {
            film=new Film(s, Status.valueOf(this.status.getSelectedItem().toString()));
        }
    }
    private void sucheFilm(String s)
    {
        if(s.equals(""))
        {
            AlertDialog.Builder builder=showAlertDialog("Es wurde kein Film eingegeben! Hole es nach!  ", "ok");
            builder.show();
        }
        else if(loadDataFromInternet()!=null)
        {
         String json=loadDataFromInternet();
         if(json!=null) {
             AlertDialog.Builder builder = showAlertDialog("Film wurde in Datenbank gefunden. Willst du damit einen neuen Film anlegen?", "Abbrechen");
             builder.setPositiveButton("Ja", new DialogInterface.OnClickListener() {
                 @Override
                 public void onClick(DialogInterface dialog, int which) {
                     //aus json filmname holen und daraus einen neuen Film erstellen und der Variable Film zuweisen
                 }
             });
             builder.show();
         }
         else
         {
             AlertDialog.Builder builder = showAlertDialog("Film wurde in Datenbank nicht gefunden. Willst du den Film selber anlgen?", "Abbrechen");
             builder.setPositiveButton("Ja", new DialogInterface.OnClickListener() {
                 @Override
                 public void onClick(DialogInterface dialog, int which) {
                     Status stat=getSelectedStatus(status.getSelectedItem().toString());
                     String name=title.getText().toString();
                     if(stat != null)
                     {
                         film=new Film(name, stat);
                     }
                 }

                 private Status getSelectedStatus(String st) {
                     if(st.equals(" "))
                     {
                         st="NICHTS";
                     }
                     if(st.equals("NICHTS")||st.equals("WARTELISTE")||st.equals("GESEHEN"))
                     {
                         return Status.valueOf(st);
                     }
                     return null;
                 }
             });
             builder.show();
         }
        }
    }

    private AlertDialog.Builder showAlertDialog(String s, String neutral)
    {
       return new AlertDialog.Builder(getApplicationContext())
                .setCancelable(false)
                .setIcon(android.R.drawable.ic_dialog_info)
                .setMessage(s)
                .setNeutralButton(neutral, null);
    }

    private String loadDataFromInternet()
    {
        String json=null;
        String filmName=this.title.getText().toString();
        SearchTask searchTask=new SearchTask(getURL("%20", filmName.split(" "), "https://movie-database-imdb-alternative.p.rapidapi.com/?page=1&r=json&s="));
        AsyncTask<String, Integer, String> asyncTask=searchTask.execute();
        try {
            json = asyncTask.get();
        } catch (ExecutionException|InterruptedException e) {
            e.printStackTrace();
        }
        return json;
    }

    private String getURL(String trenn, String[] s, String link) {
        StringBuilder sb=new StringBuilder();
        sb.append(link);
        for(String st:s)
        {
            sb.append(st.trim());
            sb.append(trenn);
        }
        String st=sb.toString().trim();
        return st.substring(0, st.length()-2);
    }
}

Die StackOverflow Seite hab ich schon besucht, bevor ich diese Seite aufgesucht habe.
 

Du musst "new AlertDialog.Builder(YourActivityClassName.this);" verwenden, nicht getApplicationContext() (wie beim Toast).
 

Du musst "new AlertDialog.Builder(YourActivityClassName.this);" verwenden, nicht getApplicationContext() (wie beim Toast).
Das erzeugt aber ebenfalls genau den gleichen Fehler, hatte ich nämlich auch schon versucht
 
Aha, du hast hoffentlich auch die richtige Klasse (NewFilmActivity.) eingesetzt?


(Du versuchst einen Dialog zu öffnen nachdem die Aktivität beendet wurde, deswegen tritt die Fehlermeldung auf)

Ansonsten ist es natürlich eine Frechheit, einen Screen vom Stacktrace zu machen anstatt ihn hier zu posten...
 
Habe den Code jetzt nur so auf dem Handy überfliegen können ... das Problem tritt laut Stacktrace ja im getFilm auf und nicht im SucheFilm. Die Zeilennummern kann ich nicht zuordnen, aber kann es sein, dass der Dialog vom sucheFilm noch nicht richtig geschlossen ist, wenn du in getFilm den nächsten öffnen willst oder so?

Ist schwer so alles am Handy nach zu vollziehen. Morgen kann ich das evtl. am Rechner in Ruhe ansehen.

Evtl. kannst du in der Zwischenzeit den ausführlichen Stacktrace mal kopieren und in code Tags hier posten.

Und das Design verwirrt mich noch etwas. Du nutzt diese Dialoge massive. Da möchte ich nicht 'falsch' zu sagen, aber so kenne ich das bisher eher nicht ... aber ich bin bezüglich Android auch kein Profi da ich das eigentlich anderen überlasse.

Testweise kannst du ja mal Dialoge auskommentieren um zu schauen, ob du dann durch diese getFilm Methode kommst ...
 
Habe den Code jetzt nur so auf dem Handy überfliegen können ... das Problem tritt laut Stacktrace ja im getFilm auf und nicht im SucheFilm. Die Zeilennummern kann ich nicht zuordnen, aber kann es sein, dass der Dialog vom sucheFilm noch nicht richtig geschlossen ist, wenn du in getFilm den nächsten öffnen willst oder so?

Ist schwer so alles am Handy nach zu vollziehen. Morgen kann ich das evtl. am Rechner in Ruhe ansehen.

Evtl. kannst du in der Zwischenzeit den ausführlichen Stacktrace mal kopieren und in code Tags hier posten.

Und das Design verwirrt mich noch etwas. Du nutzt diese Dialoge massive. Da möchte ich nicht 'falsch' zu sagen, aber so kenne ich das bisher eher nicht ... aber ich bin bezüglich Android auch kein Profi da ich das eigentlich anderen überlasse.

Testweise kannst du ja mal Dialoge auskommentieren um zu schauen, ob du dann durch diese getFilm Methode kommst ...
Das tritt bei jedem Dialog auf, deswegen kann ich auch nicht testweise welche auskommentieren, da es dann bei dem nächsten auftritt.
 
Was passiert denn, wenn Du nur mal
Java:
    private AlertDialog.Builder showAlertDialog(String s, String neutral)
    {
       return new AlertDialog.Builder(this);
    }
verwendest?
 
Das wundert mich jetzt. Da passen dann Dein Code und der Stacktrace nicht zusammen.

Laut Stacktrace ist es da der Aufruf in getFilm und um dahin zu kommen, muss er erst durch sucheFilm durch.
SucheFilm hat aber in allen Teilen bereits so einen Aufruf gehabt, also egal ob das erste if, das else if oder der else Block durchlaufen werden....

Oder habe ich da jetzt etwas übersehen?
 
Das hat nichts mit Frechheit zu tun. Da zwischen seinen Posts etwas über eine Stunde liegt, wird er vermutlich etwas verändert haben. Oder die Problematik ist etwas anders, als er glaubt.

Wenn ich die Zeit finde, werde ich nachher noch ein paar kleine Tests machen um meine Hypothese etwas zu prüfen. Aber @mihe7 ist ja auch im Thread aktiv und er hat deutlich mehr Erfahrung mit Android, so dass der TE in guten Händen sein dürfte (so er auf Fragen antwortet und so).
 
er hat deutlich mehr Erfahrung mit Android,
Das täuscht, bei mir verhält es sich wie bei Dir. In der Arbeit kümmern sich andere um die Apps, was die Programmierung dort betrifft, bin ich nur als letzte Instanz in Form des Problemlösers beteiligt 🙂

@Windows10 Jetzt habe ich das Poblem, glaube ich, gesehen. Im onClick wird getFilm aufgerufen, der Dialog wird angezeigt und am Ende von onClick ziehst Du dem Dialog mittels finish die Activity unter den Füßen weg.
 
Das täuscht, bei mir verhält es sich wie bei Dir. In der Arbeit kümmern sich andere um die Apps, was die Programmierung dort betrifft, bin ich nur als letzte Instanz in Form des Problemlösers beteiligt 🙂

Ok, du bist der "Google Search Expert" und nicht der "Android Developer Expert" 🙂

@Windows10 Jetzt habe ich das Poblem, glaube ich, gesehen. Im onClick wird getFilm aufgerufen, der Dialog wird angezeigt und am Ende von onClick ziehst Du dem Dialog mittels finish die Activity unter den Füßen weg.

Ah. Das ist mir so gar nicht aufgefallen. Gut gesehen. Dann erspare ich es mir an dieser Stelle, da die Problematik mit zwei AlertDialogen hintereinander nachzustellen. Das was Du da gefunden hast klingt erst einmal deutlich plausibler.
 
Was passiert denn, wenn Du nur mal
Java:
    private AlertDialog.Builder showAlertDialog(String s, String neutral)
    {
       return new AlertDialog.Builder(this);
    }
verwendest?

Das wundert mich jetzt. Da passen dann Dein Code und der Stacktrace nicht zusammen.

Laut Stacktrace ist es da der Aufruf in getFilm und um dahin zu kommen, muss er erst durch sucheFilm durch.
SucheFilm hat aber in allen Teilen bereits so einen Aufruf gehabt, also egal ob das erste if, das else if oder der else Block durchlaufen werden....

Oder habe ich da jetzt etwas übersehen?
Könnte so sein, dann weiß ich aber nicht, wie ich verhindere, dass ein Dialog aufgemacht wird, wenn gerade einer geöffnet ist, also angezeigt wird.
 
Das täuscht, bei mir verhält es sich wie bei Dir. In der Arbeit kümmern sich andere um die Apps, was die Programmierung dort betrifft, bin ich nur als letzte Instanz in Form des Problemlösers beteiligt 🙂

@Windows10 Jetzt habe ich das Poblem, glaube ich, gesehen. Im onClick wird getFilm aufgerufen, der Dialog wird angezeigt und am Ende von onClick ziehst Du dem Dialog mittels finish die Activity unter den Füßen weg.
Ja, ist auch meine Vermutung, ich will aber die anderen Dialoge auch anzeigen in dieser Film Activity
 
Du darfst aber die Activity nicht schließen, so lange Du den Dialog anzeigst.
Ist mir klar, weiß aber nicht wie ich das verhindere.

Hab nur eine Idee:

Die finish()-Methode nach dem show() vom AlertDialog schreiben.

Wenn ich aber einen Dialog aufmache und in der Zeit in der ein Dialog offen ist, wieder einen aufmache, wie kann ich das verhindern.
 
Die finish-Methode wird bereits nach dem show() aufgerufen. Du musst halt auf das Schließen des Dialogs reagieren (setOnDismissListener).
 
setOnDismissListener hat das Problem nicht behoben. Bekomme immer noch die gleiche Fehlermeldunng.

Habe folgenden Code geändert, der Rest blieb gleich:

Java:
 private AlertDialog.Builder showAlertDialog(String s, String neutral)
    {
       return new AlertDialog.Builder(NewFilmActivity.this)
               .setCancelable(false).setIcon(android.R.drawable.ic_dialog_info)
               .setMessage(s)
               .setNeutralButton(neutral, null)
               .setOnDismissListener(new DialogInterface.OnDismissListener() {
                   @Override
                   public void onDismiss(DialogInterface dialog) {

                   }
               });
    }
 
Sieht Dein setOnClickListener so aus?
Java:
        this.anlegen.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               getFilm(v);
               }
        });
 
Jetzt sieht es so aus:

Java:
 this.anlegen.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               getFilm(v);
//               Intent data = new Intent();
//               data.putExtra("title", film.getName());
//               data.putExtra("status", film.getStatus().toString());
//               setResult(RESULT_OK, data);
//               finish();
               }
        });
 
Jetzt werden alle Dialoge (die ich will) ohne Fehler angezeigt.

Wo soll ich jetzt die auskommentierten Codeabschnitte ausführen? Nach onClick() vom Button anlegen?
 

Zurück
Oben