J'essaie d'afficher un AlertDialog lorsque j'appuie sur un bouton d'un ViewHolder de mon adaptateur. Mais quand je lance ce crash avec le message suivant.
E / AndroidRuntime: FATAL EXCEPTION: main Processus: cl.abitsoft.todotick, PID: 4172 android.view.WindowManager $ BadTokenException: Impossible d'ajouter la fenêtre - le jeton null n'est pas valide; votre activité est-elle en cours? à android.view.ViewRootImpl.setView (ViewRootImpl.java:798)
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, View.OnClickListener { ListView listview; private CustomAdapter adapter; private Button no, button_accept; private EditText edittext_title; private Spinner spinner_classes; private RowModel rowModel; private ArrayList<RowModel> row_models; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = findViewById(R.id.fab); fab.setOnClickListener(this); DrawerLayout drawer = findViewById(R.id.drawer_layout); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); drawer.addDrawerListener(toggle); toggle.syncState(); NavigationView navigationView = findViewById(R.id.nav_view); navigationView.setNavigationItemSelectedListener(this); // Se inicializan las variables edittext_title = findViewById(R.id.main_edittext_title); spinner_classes = findViewById(R.id.main_spinner_classes); button_accept = findViewById(R.id.main_button_accept); listview = findViewById(R.id.main_listview); row_models = new ArrayList<>(); adapter = new CustomAdapter(row_models, getApplicationContext()); // AL ListView se le asigna el Adapter con el tipo de objeto que usaremos listview.setAdapter(adapter); // Creamos un arreglo del tipo String con las variables para el Spinner String[] values = {"Pagar", "Cobrar", "Llamar", "Pedir", "Comprar", "Revisar", "Otro"}; // Agregamos las variables a nuestro Spinner spinner_classes.setAdapter(new ArrayAdapter<String>(getApplicationContext(), R.layout.spinner_main, values)); // Habilitamos el click en nuestro boton button_accept.setOnClickListener(this); loadRows(); } [...]
EDIT: Ajout de MainActivity.class
public class CustomAdapter extends ArrayAdapter<RowModel> implements View.OnClickListener { private ArrayList<RowModel> DataSet; Context context; private static class ViewHolder { [...] } public CustomAdapter(ArrayList<RowModel> data, Context context) { super(context, R.layout.list_item_main, data); this.DataSet = data; this.context = context; } @Override public void onClick(View v) { int position = (Integer) v.getTag(); final Object object = getItem(position); switch (v.getId()) { case R.id.list_delete_button: AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.show(); break; } } @Override public View getView(int position, View convertView, ViewGroup parent) { [...] } }
4 Réponses :
Vous pouvez obtenir le Contexte
de votre Vue
comme ceci:
@Override public void onClick(View v) { int position = (Integer) v.getTag(); final Object object = getItem(position); switch (v.getId()) { case R.id.list_delete_button: AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext()); builder.show(); break; } }
le problème persiste. J'essaye, v.getContext (), MainActivity.getApplicationContext (), context, getContext () et tout le temps est le même problème
Désolé, je n'ai pas vu que vous avez déjà passé dans un contexte via votre constructeur. Il semble également que le plantage que vous obtenez n'est pas lié à l'obtention du contexte, mais que l'activité qui héberge l'adaptateur n'existe plus. Maintenez-vous l'adaptateur même après la destruction de l'activité, par exemple après un changement de rotation ou etc.?
Maintenant, j'ai ajouté la MainActivity
Pourquoi ajoutez-vous ceci à ma réponse au lieu de votre question?
mon mal, maintenant je le répare
Transmettez le contexte que vous avez déclaré globalement
adapter = new CustomAdapter(row_models, this);
et remplacez la ligne suivante par
adapter = new CustomAdapter(row_models, getApplicationContext());
par
AlertDialog.Builder builder = new AlertDialog.Builder(context);
J'espère que cela vous aidera.
oui, cela fonctionne parfaitement, mais pouvez-vous expliquer la différence entre getContext
et this
?
getApplicationContext () renvoie le contexte de l'ensemble de l'application selon son nom, tandis que cela faisait référence à votre activité actuelle, c'est-à-dire MainActivity dans votre cas sur lequel vous voulez que la boîte de dialogue apparaisse.
@ChristopherVivarVivar veuillez marquer la réponse (correcte) afin que d'autres personnes confrontées au même problème puissent facilement trouver la solution.
Apportez ces 3 modifications pour résoudre votre problème,
Passez d'abord "this" dans CustomAdapter.
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
obtenir l'activité dans CustomAdapter.
public CustomAdapter(ArrayList<RowModel> data, Activity activity) { super(context, R.layout.list_item_main, data); this.DataSet = data; this.context = context; }
Créez AlertDialoge en utilisant "activité".
adapter = new CustomAdapter(row_models,this);
seulement avec le premier passage fonctionne, 2 et 3 ne sont pas nécessaires, ceci :)
2 & 3 également nécessaires car si vous avez mentionné le contexte au lieu de l'activité, votre problème reste le même!
Vous devrez utiliser une instance Activity
ou vous pouvez taper du Context
vers Activity
comme ceci:
AlertDialog. Builder builder = new AlertDialog.Builder (YourActivity.this);
ou
AlertDialog.Builder builder = nouveau AlertDialog.Builder (contexte (Activité)) ;
et Où vous affichez AlertDialog
alors faites quelque chose comme ceci
if(!((Activity)context).isFinishing()) { builder.show(); }
Vous n'obtiendrez pas cela exception
J'essaye ceci, mais ne fonctionne pas, j'ai besoin de donner le contexte dans le MainActivity à l'adaptateur avec ceci
@ChristopherVivarVivar, j'ai mis à jour la réponse, vérifiez si votre problème n'est pas résolu.