【问题标题】:Alert Dialog weird trouble on Contextual Action Mode上下文操作模式下的警报对话框奇怪的问题
【发布时间】:2016-09-05 14:42:42
【问题描述】:

我有一个很奇怪的情况。我正在使用上下文操作模式来选择ListView 的多个项目。流程如下:

用户通过长按选择列表项 --> 使用操作项“操作”来选择他想要执行的操作 --> 此操作项创建一个带有 4 个列表项的AlertDialog(称为 dialog1),其中第三项调用另一个AlertDialog(称为dialog2),其中包括用于某些数据输入的EditText,然后调用一个方法来执行它。

稍后用户点击返回按钮或主页按钮退出操作模式。 问题是 dialog2 交替出现,就像用户第一次选择列表项,选择“操作”操作项并选择调用 dialog2 的第三项。现在 dialog2 将按预期显示。稍后用户点击返回按钮退出操作模式。 第二次用户执行 dialog2 未出现的相同步骤。

logcat 在这两种情况下都会显示此错误:

09-04 10:53:12.096 6299-6299/com.project.pcmanager W/InputEventReceiver:试图完成一个输入事件,但输入 事件接收器已被释放。

一些代码:

     public void sendAction(final Context context, final EventModel model, int position) {

        JSONObject object = new JSONObject();
        String[] operations = getResources().getStringArray(R.array.operations);
        // null set before is modified here
        model.setEventTitle(operations[position]);
        final String ip = model.getEventIP();
        switch (position) {
            case 0:
                try {
                    object.put("command", "power_off");
                    notifyUser();
                    LogUtils.addEntry(model.toString());
                    execCommand(ip,object);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                break;
            case 1:
                try {
                    object.put("command", "reboot");
                    notifyUser();
                    LogUtils.addEntry(model.toString());
                    execCommand(ip,object);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                break;
            case 2:
                //Show AlertDialog with EditText on it for command input
                final EditText txtCommand = new EditText(context);

                // Set some properties to EditText
                txtCommand.setPadding(16, 16, 16, 16);
                txtCommand.setMinHeight(150);
                txtCommand.setHint("Ex: ping google.com");
                txtCommand.setSingleLine();

                new AlertDialog.Builder(context)
                        .setTitle("Run a task")
                        .setView(txtCommand)
                        .setCancelable(false)
                        .setPositiveButton("Run",
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int whichButton) {
                                        String command = txtCommand.getText().toString();
                                        if (command.length() > 0) {
                                            JSONObject object = new JSONObject();
                                            try {
                                                object.put("run", command);
                                                object.put("ip", ip);
                                                notifyUser();
                                                LogUtils.addEntry(model.toString());
                                                performRemoteExec(object);

                                            } catch (JSONException e) {
                                                e.printStackTrace();
                                            }
                                        } else {
                                            Toast.makeText(context, "Please provide a command first!", Toast.LENGTH_SHORT).show();
                                        }
                                    }
                                }).setNeutralButton("Cancel", null).show();

                break;
            case 3:
                notifyUser();
                LogUtils.addEntry(model.toString());
                getScreenshot(ip);
                break;
        }
    }

@Override
    protected void onCreate(Bundle savedInstanceState) {
    listView.setAdapter(adapter);
            listView.setEmptyView(emptyView);
            listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
            listView.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {

                @Override
                public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {

                    //Change the title bar with the items selected
                    mode.setTitle(listView.getCheckedItemCount() + " selected");

                    //select the clicked item
                    adapter.toggleSelection(position);

                }

                /**
                 * Called when action mode is first created.
                 * The menu supplied will be used to generate action buttons for the action mode.
                 * @param mode ActionMode being created
                 * @param menu Menu used to populate action buttons
                 * @return true if the action mode should be created,
                 *          false if entering this mode should be aborted.
                 */
                @Override
                public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                    onContextMode = true;
                    mode.getMenuInflater().inflate(R.menu.menu_client_select_main, menu);
                    return true;
                }

                /**
                 * Called to refresh an action mode's action menu whenever it is invalidated.
                 * @return true if the menu or action mode was updated, false otherwise.
                 */
                @Override
                public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                    return false;
                }

                /**
                 * Called to report a user click on an action button.
                 * @return true if this callback handled the event,
                 *          false if the standard MenuItem invocation should continue.
                 */
                @Override
                public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                    int id = item.getItemId();

                    if (id == R.id.menu_operations) {
                        final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                                builder.setItems(R.array.operations, new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        SparseBooleanArray selectedIds = adapter.getSelectedIds();
                                        // traverse the array to find chosen clients
                                        for (int i = 0; i < selectedIds.size(); i++) {
                                            if (selectedIds.get(i)) {
                                                ClientModel item = adapter.getItem(i);
                                                String ip = item.getClientIP();
                                                String os = item.getOSType();

                                                // null will be treated soon
                                                EventModel model = new EventModel(ip, null, os);
                                                sendAction(builder.getContext(),model, which);
                                            }
                                        }
                                    }
                                });
                        builder.show();
                    }
                    return true;
                }

                /**
                 * Called when an action mode is about to be exited and destroyed.
                 */
                @Override
                public void onDestroyActionMode(ActionMode mode) {
                    onContextMode = false;
                }
            });
}

【问题讨论】:

    标签: android listview android-actionbar android-alertdialog


    【解决方案1】:

    好的,所以我自己解决了这个问题。原来罪魁祸首是我使用SparseBooleanArray 来获取选定的客户,我错了。

    在我的代码中是:

    SparseBooleanArray selectedIds = adapter.getSelectedIds();
    

    所以,我用一种新的实现技术删除了这个 SparseBooleanArray。我使用ArrayList&lt;ClientMode&gt; selectedItems 将所有选定的模型存储在我的适配器类中。

    另外,我创建了一个名为clearSelections 的简单方法,它在其中调用selectedItems.clear() 方法。根据我的应用要求,我在onDestroyActionMode 上调用此方法。

    我是怎么找到这个的? 我只是在onCreatesendAction 周围放置了一堆System.out.println 语句来找出罪魁祸首。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-28
      相关资源
      最近更新 更多