简体   繁体   中英

java.lang.ClassCastException: Activity cannot be cast to Adapter while trying to convert Activity to Fragment

I'm trying to convert Activity to Fragment and I'm sruggling to understand how to do it properly with this one.

Basically, I'm trying to adapt this MainActivity so as it fits a bottom navigation bar and besides getting lost in contexts, I'm dealing with this specific issue:

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.com, PID: 5213 java.lang.ClassCastException: com.example.com.MainActivity cannot be cast to com.example.com.adapter.NotesAdapter$OnNoteItemClick at com.example.com.adapter.NotesAdapter.(NotesAdapter.java:27) at com.example.com.RoomMarkdownActivity.onCreateView(RoomMarkdownActivity.java:54) at android.support.v4.app.Fragment.performCreateView(Fragment.java:2439) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1460) at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852) at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:802) at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625) at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411) at android.support.v4.app.FragmentManagerImpl.rem oveRedundantOperationsAndExecute(FragmentManager.java:2366) at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273) at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:733) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:6669) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

I/Process: Sending signal. PID: 5213 SIG: 9 Application terminated.

Here is a copy of the piece of code I'm working on:

public class RoomMarkdownActivity extends Fragment implements NotesAdapter.OnNoteItemClick {

    public static RoomMarkdownActivity newInstance() { return new RoomMarkdownActivity(); }

    public RecyclerView recyclerView;
    public TextView textViewMsg;
    public NoteDatabase noteDatabase;
    public List<Note> notes;
    public NotesAdapter notesAdapter;
    public int pos;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.room_markdown_activity, container, false);

        textViewMsg = view.findViewById(R.id.textview_empty);
        FloatingActionButton fab = view.findViewById(R.id.fab);
        fab.setOnClickListener(listener);
        recyclerView = view.findViewById(R.id.recycler_view);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

        notes = new ArrayList<>();
        notesAdapter = new NotesAdapter(notes, getActivity());
        recyclerView.setAdapter(notesAdapter);
        noteDatabase = NoteDatabase.getInstance(getActivity());
        new RetrieveTask(this).execute();

        return view;
    }

    private static class RetrieveTask extends AsyncTask<Void, Void, List<Note>> {

        private WeakReference<RoomMarkdownActivity> activityReference;

        RetrieveTask(RoomMarkdownActivity context) {
            activityReference = new WeakReference<>(context);
        }

        @Override
        protected List<Note> doInBackground(Void... voids) {
            if (activityReference.get() != null)
                return activityReference.get().noteDatabase.getNoteDao().getNotes();
            else
                return null;
        }

        @Override
        protected void onPostExecute(List<Note> notes) {
            if (notes != null && notes.size() > 0) {
                activityReference.get().notes.clear();
                activityReference.get().notes.addAll(notes);
                activityReference.get().textViewMsg.setVisibility(View.GONE);
                activityReference.get().notesAdapter.notifyDataSetChanged();
            }
        }
    }

    private View.OnClickListener listener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            startActivityForResult(new Intent(getActivity(), RoomMarkdownAddNoteActivity.class), 100);
        }
    };

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == 100 && resultCode > 0) {
            if (resultCode == 1) {
                notes.add((Note) data.getSerializableExtra("note"));
            } else if (resultCode == 2) {
                notes.set(pos, (Note) data.getSerializableExtra("note"));
            }
            listVisibility();
        }
    }

    @Override
    public void onNoteClick(final int pos) {
        new AlertDialog.Builder(recyclerView.getContext())
                .setTitle("Select:")
                .setItems(new String[]{"Read", "Update", "Delete"}, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        switch (i) {
                            case 0:
                                RoomMarkdownActivity.this.pos = pos;
                                startActivityForResult(
                                        new Intent(getActivity(),
                                                RoomMarkdownViewNoteActivity.class).putExtra(
                                                "note", notes.get(pos)), 100);
                                break;
                            case 1:
                                RoomMarkdownActivity.this.pos = pos;
                                startActivityForResult(
                                        new Intent(getActivity(),
                                                RoomMarkdownAddNoteActivity.class).putExtra(
                                                "note", notes.get(pos)), 100);
                                break;
                            case 2:
                                noteDatabase.getNoteDao().deleteNote(notes.get(pos));
                                notes.remove(pos);
                                listVisibility();
                                break;
                        }
                    }
                }).show();
    }

    private void listVisibility() {
        int emptyMsgVisibility = View.GONE;
        if (notes.size() == 0) {
            if (textViewMsg.getVisibility() == View.GONE)
                emptyMsgVisibility = View.VISIBLE;
        }
        textViewMsg.setVisibility(emptyMsgVisibility);
        notesAdapter.notifyDataSetChanged();
    }

    @Override
    public void onDestroy() {
        noteDatabase.cleanUp();
        super.onDestroy();
    }

}

And here is the adapter:

public class NotesAdapter extends RecyclerView.Adapter<NotesAdapter.BeanHolder> {

    private List<Note> list;
    public Context context;
    private LayoutInflater layoutInflater;
    private OnNoteItemClick onNoteItemClick;

    public NotesAdapter(List<Note> list, Context context) {
        layoutInflater = LayoutInflater.from(context);
        this.list = list;
        this.context = context;
        this.onNoteItemClick = (OnNoteItemClick) context;
    }

    @Override
    public BeanHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = layoutInflater.inflate(R.layout.room_markdown_note_list_item, parent, false);
        return new BeanHolder(view);
    }

    @Override
    public void onBindViewHolder(BeanHolder holder, int position) {
        Log.e("bind", "onBindViewHolder: " + list.get(position));
        holder.textViewTitle.setText(list.get(position).getTitle());
    }

    @Override
    public int getItemCount() {
        return list.size();
    }

    public class BeanHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        TextView textViewTitle;

        private BeanHolder(View itemView) {
            super(itemView);
            itemView.setOnClickListener(this);
            textViewTitle = itemView.findViewById(R.id.textview_title);
        }

        @Override
        public void onClick(View view) {
            onNoteItemClick.onNoteClick(getAdapterPosition());
        }
    }

    public interface OnNoteItemClick {
        void onNoteClick(int pos);
    }

}

It seems there's something broken between notesAdapter = new NotesAdapter(notes, getActivity()); and this.onNoteItemClick = (OnNoteItemClick) context; , but I couldn't find a good alternative to getActivity() and I guess I solved this one earlier in another approach, however, it was still throwing another similar error if I recall correctly (this file is full of this and I don't doubt some getActivity() are misplaced).

The code as is compiles, but, as soon as the button that'd call the specific Fragment to the screen is clicked, the error is thrown and the app stops running immediately.

I thank you in advance for the attention and help and, please, let me know if you need to know more about this issue so as I'm able to bring more information here.

You cannot cast Activity to OnNoteItemClick because you implement it in your fragment, you can assign a OnNoteItemClick to your adapter so you can change your code to : adapter:

public NotesAdapter(List<Note> list, OnNoteItemClick onNoteItemClick) {
    layoutInflater = LayoutInflater.from(context);
    this.list = list;
    this.context = context;
    this.onNoteItemClick = onNoteItemClick;
}

initialize your adapter in fragment this way:

notesAdapter = new NotesAdapter(notes, this); //Your class implements OnNoteItemClick interface so you can use 'this'

replace

notesAdapter = new NotesAdapter(notes, getActivity());

with

notesAdapter = new NotesAdapter(notes, RoomMarkdownActivity.this);

Thanks to what Mike M. and Reza.Abedini said among answers and comments I was able to understand what was happening and to overcome this issue.

The problem was in the Adapter that was prepared to get Context from Activity so I had to convert the parameter to Fragment and it ended up working like this:

public NotesAdapter(List<Note> list, RoomMarkdownActivity fragment) {
    this.layoutInflater = LayoutInflater.from(fragment.getActivity());
    this.list = list;
    this.fragment = fragment;
    this.onNoteItemClick = fragment;
}

And the Fragment like:

public class RoomMarkdownActivity extends Fragment implements NotesAdapter.OnNoteItemClick {

    public static RoomMarkdownActivity newInstance() {
        return new RoomMarkdownActivity();
    }

    RecyclerView recyclerView;
    TextView textViewMsg;
    NoteDatabase noteDatabase;
    List<Note> notes;
    NotesAdapter notesAdapter;
    int pos;

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.room_markdown_activity, container, false);
        textViewMsg = view.findViewById(R.id.textview_empty);
        FloatingActionButton fab = view.findViewById(R.id.fab);
        fab.setOnClickListener(listener);
        recyclerView = view.findViewById(R.id.recycler_view);
        initializeViews();
        displayList();
        return view;
    }

    private void displayList() {
        noteDatabase = NoteDatabase.getInstance(getActivity());
        new RetrieveTask(this).execute();
    }

    private static class RetrieveTask extends AsyncTask<Void, Void, List<Note>> {

        private WeakReference<RoomMarkdownActivity> activityReference;

        RetrieveTask(RoomMarkdownActivity context) {
            activityReference = new WeakReference<>(context);
        }

        @Override
        protected List<Note> doInBackground(Void... voids) {
            if (activityReference.get() != null)
                return activityReference.get().noteDatabase.getNoteDao().getNotes();
            else
                return null;
        }

        @Override
        protected void onPostExecute(List<Note> notes) {
            if (notes != null && notes.size() > 0) {
                activityReference.get().notes.clear();
                activityReference.get().notes.addAll(notes);
                activityReference.get().textViewMsg.setVisibility(View.GONE);
                activityReference.get().notesAdapter.notifyDataSetChanged();
            }
        }
    }

    public void initializeViews() {
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        notes = new ArrayList<>();
        notesAdapter = new NotesAdapter(notes, this);
        recyclerView.setAdapter(notesAdapter);
    }

    private View.OnClickListener listener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            startActivityForResult(new Intent(getActivity(), RoomMarkdownAddNoteActivity.class), 100);
        }
    };

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == 100 && resultCode > 0) {
            if (resultCode == 1) {
                notes.add((Note) data.getSerializableExtra("note"));
            } else if (resultCode == 2) {
                notes.set(pos, (Note) data.getSerializableExtra("note"));
            }
            listVisibility();
        }
    }

    @Override
    public void onNoteClick(final int pos) {
        new AlertDialog.Builder(getActivity())
                .setTitle("Select:")
                .setItems(new String[]{"Read", "Update", "Delete"}, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        switch (i) {
                            case 0:
                                RoomMarkdownActivity.this.pos = pos;
                                startActivityForResult(
                                        new Intent(getActivity(),
                                                RoomMarkdownViewNoteActivity.class).putExtra(
                                                "note", notes.get(pos)), 100);
                                break;
                            case 1:
                                RoomMarkdownActivity.this.pos = pos;
                                startActivityForResult(
                                        new Intent(getActivity(),
                                                RoomMarkdownAddNoteActivity.class).putExtra(
                                                "note", notes.get(pos)), 100);
                                break;
                            case 2:
                                noteDatabase.getNoteDao().deleteNote(notes.get(pos));
                                notes.remove(pos);
                                listVisibility();
                                break;
                        }
                    }
                }).show();
    }

    public void listVisibility() {
        int emptyMsgVisibility = View.GONE;
        if (notes.size() == 0) {
            if (textViewMsg.getVisibility() == View.GONE)
                emptyMsgVisibility = View.VISIBLE;
        }
        textViewMsg.setVisibility(emptyMsgVisibility);
        notesAdapter.notifyDataSetChanged();
    }

    @Override
    public void onDestroy() {
        noteDatabase.cleanUp();
        super.onDestroy();
    }

}

Thank you very much for the help and I hope this question/answer helps others as well!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM