ViewLolder的onLongClick中的ClassCastException

时间:2017-07-07 18:58:53

标签: android android-recyclerview android-viewholder onlongclicklistener

我跟随this教程在我的RecyclerView中实现多选,但是当我执行长按时,我得到了以下运行时异常:

java.lang.ClassCastException: com.abdralabs.talksee.MyApplication cannot be cast to android.support.v7.app.AppCompatActivity
                                                                       at com.abdralabs.talksee.IMListAdapter$IMListViewHolder.onLongClick(IMListAdapter.java:116)
                                                                       at android.view.View.performLongClick(View.java:5308)
                                                                       at android.view.View$CheckForLongPress.run(View.java:21522)
                                                                       at android.os.Handler.handleCallback(Handler.java:815)
                                                                       at android.os.Handler.dispatchMessage(Handler.java:104)
                                                                       at android.os.Looper.loop(Looper.java:207)
                                                                       at android.app.ActivityThread.main(ActivityThread.java:5740)
                                                                       at java.lang.reflect.Method.invoke(Native Method)
                                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
                                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:766)

活动代码:

public class IMListActivity extends AppCompatActivity implements Sertivity{

private RecyclerView recyclerView;
private IMListAdapter imListAdapter;
private List<Chat> chatList = new ArrayList<>();
List<String> stringList;
ActiveChatsDB activeChatsDB;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_imlist);
    Toolbar toolbar = (Toolbar)findViewById(R.id.imlist_toolbar);
    setSupportActionBar(toolbar);
    setBackButtonOnToolbar();

    recyclerView = (RecyclerView)findViewById(R.id.rv_im_list);
    imListAdapter = new IMListAdapter(chatList, getApplicationContext());
    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
    recyclerView.setAdapter(imListAdapter);
    prepareChatListData();
}

private void prepareChatListData() {
    String friend;
    String latestMessage;
    activeChatsDB = new ActiveChatsDB(IMListActivity.this);
    stringList = activeChatsDB.getChatList();
    activeChatsDB.close();
    for (int i=0; i<stringList.size(); i++) {
        friend = stringList.get(i);
        DBAct dbAct = new  DBAct(IMListActivity.this,friend);
        latestMessage = dbAct.getLatestMessage();
        dbAct.close();
        Chat chat = new Chat(friend, latestMessage);
        chatList.add(chat);
    }
    imListAdapter.notifyDataSetChanged();
}

private void setBackButtonOnToolbar(){
    if(getSupportActionBar() != null){
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDisplayShowHomeEnabled(true);
    }
}



public RecyclerView getRecyclerView() {
    return recyclerView;
}

}

适配器代码:

public class IMListAdapter extends RecyclerView.Adapter <com.abdralabs.talksee.IMListAdapter.IMListViewHolder> {

private List<Chat> chatList = new ArrayList<Chat>() ;
private Context ctx;
private MultiSelector multiSelector = new MultiSelector();
private ModalMultiSelectorCallback modalMultiSelectorCallback =
        new ModalMultiSelectorCallback(multiSelector) {
            @Override
            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                if (item.getItemId() == R.id.item_delete) {
                    mode.finish();

                    for (int i = chatList.size(); i >= 0; i--) {
                        if (multiSelector.isSelected(i, 0)) { // (1)
                            // remove item from list
                            ((IMListActivity)ctx).getRecyclerView().getAdapter().notifyItemRemoved(i);
                        }
                    }

                    multiSelector.clearSelections(); // (2)
                    return true;

                }
                return false;
            }

            @Override
            public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
                super.onCreateActionMode(actionMode, menu);
                ((AppCompatActivity)ctx).getMenuInflater().inflate(R.menu.contextual_menu_friends, menu);
                return true;
            }
        };

public IMListAdapter(List<Chat> chatList, Context ctx){
    this.chatList = chatList;
    this.ctx = ctx;
}


@Override
public com.abdralabs.talksee.IMListAdapter.IMListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_list_row,parent,false);
    return new com.abdralabs.talksee.IMListAdapter.IMListViewHolder(itemView, chatList, ctx);    }

@Override
public void onBindViewHolder(com.abdralabs.talksee.IMListAdapter.IMListViewHolder holder, int position) {
    Chat chat = chatList.get(position);
    holder.name.setText(chat.getName());
    holder.recentMsg.setText(chat.getRecentMessage());
}

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

public class IMListViewHolder extends SwappingHolder implements View.OnClickListener, View.OnLongClickListener{
    public TextView name;
    public TextView recentMsg;
    List<Chat> chatList = new ArrayList<Chat>();
    Context ctx;

    public IMListViewHolder(View itemView, List<Chat> chatList, Context ctx) {
        super(itemView, multiSelector);
        this.chatList = chatList;
        this.ctx = ctx;
        itemView.setOnClickListener(this);
        itemView.setOnLongClickListener(this);
        itemView.setLongClickable(true);
        name = (TextView) itemView.findViewById(R.id.name_chat);
        recentMsg = (TextView)itemView.findViewById(R.id.tv_recent_msg_im_list);
    }

    @Override
    public void onClick(View v) {
        int position = getAdapterPosition();
        Chat chat = this.chatList.get(position);
        Intent intent = new Intent(this.ctx, IMActivity.class);
        intent.putExtra("otherUserName",chat.getName());
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        this.ctx.startActivity(intent);


    }

    @Override
    public boolean onLongClick(View v) {
        if (!multiSelector.isSelectable()) { // (3)
            ((AppCompatActivity)ctx).startSupportActionMode(modalMultiSelectorCallback);
            multiSelector.setSelectable(true); // (4)
            multiSelector.setSelected(com.abdralabs.talksee.IMListAdapter.IMListViewHolder.this, true); // (5)
            return true;
        }
        return false;
    }
}

}

我不知道我应该如何进行正确的选型。请帮忙。

编辑1:

我尝试将onLongClick代码替换为

public boolean onLongClick(View v) {
        if (!multiSelector.isSelectable()) { // (3)
            ((IMListActivity)ctx).startSupportActionMode(modalMultiSelectorCallback);
            multiSelector.setSelectable(true); // (4)
            multiSelector.setSelected(IMListViewHolder.this, true); // (5)
            return true;
        }
        return false;
    }
如Sachin Bahukhandi建议的那样,但我得到同样的错误

java.lang.ClassCastException: com.abdralabs.talksee.MyApplication cannot be cast to com.abdralabs.talksee.IMListActivity
                                                                     at com.abdralabs.talksee.IMListAdapter$IMListViewHolder.onLongClick(IMListAdapter.java:116)
                                                                     at android.view.View.performLongClick(View.java:5308)
                                                                     at android.view.View$CheckForLongPress.run(View.java:21522)
                                                                     at android.os.Handler.handleCallback(Handler.java:815)
                                                                     at android.os.Handler.dispatchMessage(Handler.java:104)
                                                                     at android.os.Looper.loop(Looper.java:207)
                                                                     at android.app.ActivityThread.main(ActivityThread.java:5740)
                                                                     at java.lang.reflect.Method.invoke(Native Method)
                                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
                                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:766)

在我跟随代码的tutorial之内:

@Override
public boolean onLongClick(View view) {
    if (!mMultiSelector.isSelectable()) {
        ((AppCompatActivity) getActivity()).startSupportActionMode(mActionModeCallback); // (2)
        mMultiSelector.setSelectable(true);
        mMultiSelector.setSelected(MyViewHolder.this, true);
        return true;
    }
    return false;
}

在上面的代码中,从Viewholder以某种方式调用getActivity,并将类型转换为AppCompatActivity。我不知道如何直接从ViewHolder调用getActivity,因为我收到错误所以我尝试输入一个上下文对象(通过适配器构造函数从我的Activity传递)到AppCompatActivity。所以我不知道我在这里做错了什么。

2 个答案:

答案 0 :(得分:0)

在您发布的代码中,应用程序崩溃了,因为它无法将Context强制转换为AppCompatActivity

 @Override
public boolean onLongClick(View v) {
    if (!multiSelector.isSelectable()) { // (3)
        ((AppCompatActivity)ctx).startSupportActionMode(modalMultiSelectorCallback);
        multiSelector.setSelectable(true); // (4)
        multiSelector.setSelected(com.abdralabs.talksee.IMListAdapter.IMListViewHolder.this, true); // (5)
        return true;
    }
    return false;
}

所以我建议更换

((AppCompatActivity)ctx).startSupportActionMode(modalMultiSelectorCallback);
        multiSelector.setSelectable(true); // (4)

YourActivity

((IMListActivity)ctx).startSupportActionMode(modalMultiSelectorCallback);
        multiSelector.setSelectable(true); // (4)

希望这有帮助。

答案 1 :(得分:0)

所以我通过将活动引用传递给适配器的构造函数并调用

来解决这个问题
imListActivity.startSupportActionMode(modalMultiSelectorCallback);

而不是这样做

((IMListActivity)ctx).startSupportActionMode(modalMultiSelectorCallback);