2017-10-06 56 views
0

我在MainActivity.java中有RecyclerView。在每個RecyclerView行中,我有一個按鈕,當它被按下時,它應該打開一個帶有RecyclerView列表的自定義片段對話框(這是一個多選對話框)。ClassCastException:應用程序在使用DialogFragment時崩潰

在我的SecondActivity.java,這是我的其他活動,我也有同樣的按鈕,應該做同樣的事情(這就是爲什麼我需要的模態是片段對話框)。在我的SecondActivity.java中,沒有RecyclerView,它只是一個單獨的帖子(詳細信息頁面)。

我的問題:

當我點擊按鈕對SecondActivity.java彈出,它打開的對話框彈出片段正常。當我這樣做對任何單獨的行同樣在我的RecyclerView(這是MainActivity.java),我得到一個錯誤ClassCastException

java.lang.ClassCastException: com.example.appname.MainActivity cannot be cast to interfaces.DialogCommunicator$Communicator 

我的代碼:

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"); 

職位清單Adapter.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); 
    } 

} 

崩潰日誌:

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) 

我這是在PostsListAdapter.javaSecondActivity.java實現該接口。這是一個回調方法,所以我可以響應每個單獨的動作並知道在片段對話框彈出窗口中單擊了哪個項目。

因此,我已經正確構建了對話框片段,因爲它在列表之外的正常活動中工作,但對於RecyclerView列表中的每一行,該對話框片段由於ClassCastException而崩潰。爲什麼?

回答

2

你的崩潰是非常明確的:

MainActivity cannot be cast to DialogCommunicator$Communicator

根據你張貼的東西,你有沒有在MainActivity實現了這個接口。你說:

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

機會是非常好的,你應該從PostsListAdapter刪除implements DialogCommunicator.Communicator行並將其添加到MainActivity來代替(移動實際執行爲好,當然)。

的事實真相原因是這一行:

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

你傳遞getActivity()作爲Context參數適配器的構造。這樣會很好,除了你的對話框的構造函數將這個Context實例轉換爲你的接口。所以每個Activity這個對話框可以顯示在必須實現你的界面。

+0

YES!從'PostsListAdapter.java'中刪除'實現DialogCommunicator.Communicator'並將其添加到'MainActivity.java'中是個問題。 @Anonymous也是對的,我不小心把'getActivity()'而不是'getContext()',那個部分意外地滑倒了。它正在崩潰,因爲它試圖使用基於未實現它的'MainActivity'上下文的接口。 4個星期的痛苦與一個愚蠢的錯誤,終於結束了。謝謝。 – busuu

3

不是傳遞上下文的對象,你可以使用parent.getContext().

此外,在獲得的onCreateViewHolder的construtor的onBindViewholder你忘了類型轉換viewholder。添加

MultiDialogViewHolder viewholder=(MultiDialogViewHolder)holder; 

然後訪問viewholder.getItemTextView().setText(item);

而且typcasting適配器的情況下在你的對話片段應該實現在對話片段

public class CustomDialogFragment extends DialogFragment implements DialogCommunicator { 

//override the method 
} 

編輯DialogCommunicatorDialogCommunicator。新增implementaion:

也是主要問題的錯誤發生是因爲上下文。 這裏通過MultiDialogAdapter adapter=new MultiDialogAdapter(getContext(), itemsList)

如果您將getActivity()傳遞給適配器,那麼您的相應活動必須實現接口DialogCommunicator,並且回調來到活動而不是CustomDialogFragment

所以通過getContext()而不是getActivity(),因爲CustomDialogFragment實現的是接口而不是活動。

+0

我把Communicator接口的try/catch塊從構造函數移到'onCreateViewHolder'就像你說的那樣,它仍然崩潰。如果開頭的類型是相同的,我沒有看到類似於相同的查看者的類型,但它仍然崩潰。還實現了CustomDialogFragment中的接口,仍然崩潰。 – busuu

+0

你可以發佈日誌?以前你沒有實現該DialogFragment,所以你得到的錯誤 – Anonymous

+0

更新後 – busuu