No se puede agregar Window, Token no es un error válido cuando se hace clic en un Spinner

Tengo una aplicación de Android cuando se hace clic en una opción de una barra lateral que va a un fragmento, y luego en otro fragmento que tiene botones de radio clicables. Al hacer clic en ellos, se creará una ventana emergente con algunos campos de texto en ella.

Básicamente esto es cómo va el flujo,

Actividad -> Fragmento 1 -> Fragmento 2 -> PopupWindow

Y tengo un spinner en este PopupWindow, pero cuando hago clic en él para seleccionar un valor que lanza la siguiente excepción. No entiendo por qué sucede esto.

Process: com.informaticsint.claimassistant, PID: 5045 android.view.WindowManager$BadTokenException: Unable to add window -- token android.view.ViewRootImpl$W@945936c is not valid; is your activity running? at android.view.ViewRootImpl.setView(ViewRootImpl.java:849) at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:337) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91) at android.widget.PopupWindow.invokePopup(PopupWindow.java:1329) at android.widget.PopupWindow.showAsDropDown(PopupWindow.java:1155) at android.widget.ListPopupWindow.show(ListPopupWindow.java:791) at android.widget.Spinner$DropdownPopup.show(Spinner.java:1366) at android.widget.Spinner.performClick(Spinner.java:828) at android.view.View$PerformClick.run(View.java:22526) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:158) at android.app.ActivityThread.main(ActivityThread.java:7224) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 

Este es el código Spinner que causa el problema. Cuál está en la clase de AsignaciónDetailsActivity mencionada abajo, método de showDamagedItemEntryPopup ()

  statusSpinner = (Spinner)popupView.findViewById(R.id.popup_status_spinner); ArrayAdapter<String> statusSpinnerArrayAdapter = new ArrayAdapter<String>(AssignmentDetailsActivity.this, android.R.layout.simple_spinner_item, statusSpinnerArray); statusSpinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); statusSpinner.setAdapter(statusSpinnerArrayAdapter); 

Este es mi método que crea el popup que está en mi clase AssignmentDetailsActivity

 public void showDamagedItemEntryPopup(RadioButton radioButton, View view){ LayoutInflater layoutInflater = (LayoutInflater)getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); View popupView = layoutInflater.inflate(R.layout.component_selection_popup, null); final PopupWindow popupWindow = new PopupWindow( popupView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); // Set popup Animation style popupWindow.setAnimationStyle(R.style.popupAnimation); Button buttonClose = (Button)popupView.findViewById(R.id.close_add_component_btn); // Close button damaged item popop window buttonClose.setOnClickListener(new Button.OnClickListener(){ @Override public void onClick(View v) { popupWindow.dismiss(); } }); originalAmount = (EditText)popupView.findViewById(R.id.popup_add_component_original_amount); customerContribution = (EditText)popupView.findViewById(R.id.popup_percentage); quantity = (EditText)popupView.findViewById(R.id.popup_quantity); finalAmount = (EditText)popupView.findViewById(R.id.popup_add_component_final_amount); remarks = (EditText)popupView.findViewById(R.id.popup_add_component_remarks); // Item Spinner itemSpinnerArray = new ArrayList<String>(); itemSpinnerArray.add("Select Item"); // Status Spinner ArrayList<String> statusSpinnerArray = new ArrayList<String>(); statusSpinnerArray.add("FDR"); statusSpinnerArray.add("DR"); statusSpinnerArray.add("SP"); damageComponenetAutoCompleteTextview = (AutoCompleteTextView) popupView.findViewById(R.id.popup_damage_component_item); damageComponenetAutoCompleteTextview.requestFocus(); ArrayAdapter<String> itemSpinnerArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, itemSpinnerArray); damageComponenetAutoCompleteTextview.setThreshold(1); damageComponenetAutoCompleteTextview.setAdapter(itemSpinnerArrayAdapter); damageComponenetAutoCompleteTextview.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { itemSpinnerValue = (String) parent.getItemAtPosition(position); Log.d("SK-->", "----------------------------------------------------------"); Log.d("SK-->","itemSpinnerValue: " + itemSpinnerValue); } }); statusSpinner = (Spinner)popupView.findViewById(R.id.popup_status_spinner); ArrayAdapter<String> statusSpinnerArrayAdapter = new ArrayAdapter<String>(AssignmentDetailsActivity.this, android.R.layout.simple_spinner_item, statusSpinnerArray); statusSpinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); statusSpinner.setAdapter(statusSpinnerArrayAdapter); //Creating a text Watcher TextWatcher textWatcher = new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void afterTextChanged(Editable editable) { //here, after we introduced something in the EditText we get the string from it //String answerString = originalAmount.getText().toString(); if (originalAmount.getText().toString().trim().equals("") || customerContribution.getText().toString().trim().equals("") || quantity.getText().toString().trim().equals("")) { // Error , one or more editText are empty } else { calculateFinalAmount(); } //and now we make a Toast //modify "yourActivity.this" with your activity name .this //Toast.makeText(yourActivity.this,"The string from EditText is: "+answerString,0).show(); } }; // Adding Text Watcher to our text boxes originalAmount.addTextChangedListener(textWatcher); customerContribution.addTextChangedListener(textWatcher); quantity.addTextChangedListener(textWatcher); // Show the popup popupWindow.showAtLocation(view, Gravity.CENTER, 0, 0); } public void onSaveItem(View view) { statusSpinnerValue = (String) statusSpinner.getItemAtPosition(statusSpinner.getSelectedItemPosition()); statusSpinnerValue = "ABC"; itemSpinnerValue = "TEST ITEM"; originalAmount.setText("50"); customerContribution.setText("25"); quantity.setText("1"); if(itemSpinnerValue.matches("Select Item") ||itemSpinnerValue.matches("") || statusSpinnerValue.matches("") || originalAmount.getText().toString().matches("") || customerContribution.getText().toString().matches("") || quantity.getText().toString().matches("")){ AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("ERROR!"); builder.setMessage("Please Fill the Required Fields.") .setCancelable(false) .setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { //do things dialog.dismiss(); } }); AlertDialog alert = builder.create(); alert.show(); } else{ Log.e("TEST", "Check Passed"); Date date = new Date(); if(mDbHandler.itemAlreadyExist(reportID,"item_name", itemSpinnerValue, "DamageComponent") == false){ mDbHandler.addDamageComponent(reportID, itemSpinnerValue, statusSpinnerValue, originalAmount.getText().toString(), Double.parseDouble(customerContribution.getText().toString()), Integer.parseInt(quantity.getText().toString()), finalAmount.getText().toString(), remarks.getText().toString()); mDbHandler.updateReport(reportID, date.toString(), "time_last_modified"); Toast.makeText(this,"Component Successfully Added",Toast.LENGTH_SHORT).show(); } else{ AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("ERROR!"); builder.setMessage("Item Already Exist.") .setCancelable(false) .setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { //do things dialog.dismiss(); } }); AlertDialog alert = builder.create(); alert.show(); } mDbHandler.close(); } } 

Pasamos 2 días exactamente por el mismo problema 🙁

La única solución que encuentro es utilizar el hilandero en modo de diálogo

 android:spinnerMode="dialog" 

Me alegro de ayudarte de nuevo, echa un vistazo a las respuestas de esta pregunta. Estás mostrando popup demasiado pronto para que tengas que delay la carrera como esta

  view.post(new Runnable() { public void run() { popupWindow.showAtLocation(view, Gravity.CENTER, 0, 0); } }); 

ACTUALIZACIÓN:

O intentar

 new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { @Override public void run() { popupWindow.showAtLocation(view, Gravity.CENTER, 0, 0); } }, 1000); //Delay one second 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.