J'ai un RecyclerView
dans mon MainActivity.java
. Dans chaque ligne de RecyclerView, j'ai un bouton, et quand il est pressé, il est censé ouvrir un dialogue de fragment personnalisé avec la liste de RecyclerView dedans (c'est une boîte de dialogue multi-choix).ClassCastException: l'application se bloque lors de l'utilisation de DialogFragment
Dans mon SecondActivity.java
, qui est mon autre activité, j'ai également le même bouton qui est censé faire la même chose (c'est pourquoi j'ai besoin de la boîte de dialogue modale pour être le fragment). Dans mon SecondActivity.java
, il n'y a pas de RecyclerView, c'est juste un seul article (page de détails).
Mon problème:
Lorsque je clique sur le bouton pour le menu contextuel sur SecondActivity.java
, il ouvre le fragment de dialogue pop-up normalement. Quand je fais la même chose pour une ligne individuelle dans mon RecyclerView (qui est en MainActivity.java
), je reçois une erreur ClassCastException
:
java.lang.ClassCastException: com.example.appname.MainActivity cannot be cast to interfaces.DialogCommunicator$Communicator
Mon code:
SecondActivity.java
//*****************//
// THIS CODE WORKS //
//*****************//
// This code will run when the button is clicked.
// postOptions is a string array of menu items.
Bundle args = new Bundle();
args.putStringArray("displaymenu", postOptions);
mDialogFragment = new CustomDialogFragment();
mDialogFragment.setArguments(args);
mDialogFragment.show(getSupportFragmentManager(), "title");
PostsListAdapter.java
//***************************//
// THIS CODE CRASHES THE APP //
//***************************//
// This code is planted in onClick method listener in onBindViewHolder
// for the button that's supposed to open the fragment dialog.
FragmentManager fm = ((MainActivity) mContext).getSupportFragmentManager();
String[] items = mContext.getResources().getStringArray(R.array.post_options);
CustomDialogFragment customDialogFragment = CustomDialogFragment.newInstance(items);
customDialogFragment.show(fm, "title");
CustomDialogFragment.java
public class CustomDialogFragment extends DialogFragment {
private RecyclerView mRecyclerView;
public CustomDialogFragment() {
// Empty constructor is required for DialogFragment
// Make sure not to add arguments to the constructor
// Use `newInstance` instead as shown below
}
public static CustomDialogFragment newInstance(String[] items) {
CustomDialogFragment customDialogFragment = new CustomDialogFragment();
Bundle args = new Bundle();
args.putStringArray("displaymenu", items);
customDialogFragment.setArguments(args);
return customDialogFragment;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.layout_multiselect_dialog, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Bundle args = getArguments();
String[] items = args.getStringArray("displaymenu");
List<String> itemsList = Arrays.asList(items);
// THIS LINE CRASHES ON POSTSLISTADAPTER!!!
MultiDialogAdapter adapter = new MultiDialogAdapter(getActivity(), itemsList);
mRecyclerView = (RecyclerView) view.findViewById(R.id.items_recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.setAdapter(adapter);
getDialog().setTitle(null);
}
}
MultiDialogAdapter.java
public class MultiDialogAdapter extends RecyclerView.Adapter<MultiDialogViewHolder> {
private List<String> mItems;
private LayoutInflater mInflater;
private CustomFonts mCustomFont;
private DialogCommunicator.Communicator mCommunicator;
public MultiDialogAdapter(Context context, List<String> items) {
this.mInflater = LayoutInflater.from(context);
this.mItems = items;
this.mCustomFont = new CustomFonts(context);
try {
mCommunicator = (DialogCommunicator.Communicator) context;
} catch (ClassCastException e) {
// THIS IS WHERE THE CLASSCASTEXCEPTION HAPPENS!
throw new ClassCastException(context.toString());
}
}
@Override
public MultiDialogViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.layout_multiselect_dialog_row, parent, false);
return new MultiDialogViewHolder(view);
}
@Override
public void onBindViewHolder(MultiDialogViewHolder holder, int position) {
final String item = mItems.get(position);
holder.getItemTextView().setText(item);
holder.getItemTextView().setTypeface(mCustomFont.getPrimaryFontMedium());
holder.getItemTextView().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCommunicator.onDialogButtonResponse(item);
}
});
}
@Override
public int getItemCount() {
return mItems.size();
}
}
class MultiDialogViewHolder extends RecyclerView.ViewHolder {
private TextView mItemTextView;
public MultiDialogViewHolder(View rootView) {
super(rootView);
mItemTextView = (TextView) rootView.findViewById(R.id.item_text_view);
}
public TextView getItemTextView() {
return mItemTextView;
}
}
DialogCommunicator.java
public class DialogCommunicator {
public interface Communicator {
public void onDialogButtonResponse(String responseMessage);
}
}
journal Crash:
10-06 14:35:12.353 21683-21683/com.example.appname E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.appname, PID: 21683
java.lang.ClassCastException: [email protected]
at adapters.MultiDialogAdapter.<init>(MultiDialogAdapter.java:40)
at fragments.CustomDialogFragment.onViewCreated(CustomDialogFragment.java:60)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1430)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1740)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1809)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:799)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2580)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2367)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2322)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2229)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:700)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
J'ai cette interface qui est mis en œuvre PostsListAdapter.java
et SecondActivity.java
. Ceci est une méthode de rappel afin que je puisse répondre à chaque action individuelle et savoir quel élément est cliqué dans la fenêtre contextuelle du fragment. Donc, j'ai construit le fragment de dialogue correctement car il fonctionne dans une activité normale en dehors d'une liste, mais pour chaque ligne dans une liste RecyclerView, ce fragment de dialogue bloque l'application à cause de ClassCastException
. Pourquoi?
OUI! Supprimer le 'implements DialogCommunicator.Communicator' de' PostsListAdapter.java' et l'ajouter dans 'MainActivity.java' était le problème. @Anonymous avait aussi raison, j'ai accidentellement mis 'getActivity()' au lieu de 'getContext()', cette partie a glissé accidentellement. Il s'est écrasé parce qu'il essayait d'utiliser l'interface basée sur le contexte 'MainActivity' qui ne l'a pas implémenté. 4 semaines d'agonie avec un bug stupide, est enfin terminée. Je vous remercie. – busuu