2017-10-06 6 views
0

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?

Répondre

2

Votre accident est très explicite:

MainActivity cannot be cast to DialogCommunicator$Communicator

Selon ce que vous avez posté, vous n'avez pas mis en œuvre cette interface dans MainActivity. Vous avez dit:

I have that interface which is implemented in PostsListAdapter.java and SecondActivity.java .

Les chances sont très bonnes que vous devez supprimer la ligne de implements DialogCommunicator.CommunicatorPostsListAdapter et l'ajouter à la place MainActivity (et déplacer la mise en œuvre effective et, bien sûr).

La cause débrouille est cette ligne:

MultiDialogAdapter adapter = new MultiDialogAdapter(getActivity(), itemsList); 

vous passez getActivity() comme argument Context au constructeur de votre carte. Ce serait bien, sauf que le constructeur de votre boîte de dialogue envoie alors cette instance Context à votre interface. Donc, tous les Activity dans lesquels cette boîte de dialogue pourrait être affichée doivent implémenter votre interface.

+0

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

3

lieu de contexte qui passe comme un objet que vous pouvez obtenir le construtor dans le onCreateViewHolder en utilisant parent.getContext().

également dans le onBindViewholder vous avez oublié de typer viewholder.Ajouter

MultiDialogViewHolder viewholder=(MultiDialogViewHolder)holder; 

ensuite accéder à viewholder.getItemTextView().setText(item);

également avant typcasting le contexte dans l'adaptateur de votre fragment de dialogue devrait mettre en œuvre DialogCommunicator .Add implementaion de DialogCommunicator dans le fragment de dialogue

public class CustomDialogFragment extends DialogFragment implements DialogCommunicator { 

//override the method 
} 

EDIT:

Aussi problème principal l'erreur l'apparition est à cause du contexte. Passez ici MultiDialogAdapter adapter=new MultiDialogAdapter(getContext(), itemsList).

Si vous transmettez getActivity() à l'adaptateur, votre activité correspondante doit implémenter l'interface DialogCommunicator et le rappel arrive à l'activité au lieu de CustomDialogFragment.

Passez donc getContext() au lieu de getActivity() car CustomDialogFragment implémente l'interface et non l'activité.

+0

J'ai déplacé le bloc try/catch de l'interface Communicator du constructeur à 'onCreateViewHolder' comme vous l'avez dit, il se bloque toujours. Je ne vois pas l'intérêt de typer le même viewholder si c'est le même type pour commencer, mais il se bloque toujours. Également implémenté l'interface dans CustomDialogFragment, se bloque toujours. – busuu

+0

Pouvez-vous poster le journal? Précédemment vous n'aviez pas implémenté ce DialogFragment de sorte que vous obteniez l'erreur – Anonymous

+0

Mis à jour le message – busuu