Исключение за пределы при использовании массива другого класса в другом классе

#android #arrays #static #indexoutofboundsexception

#Android #массивы #статический #исключение indexoutofboundsexception

Вопрос:

Я добавил действие для викторины в свое приложение. Я использую целочисленный массив selected_options для хранения параметров, выбранных пользователем. Тест показывает пользователю 5 вопросов за попытку и сохраняет их в массиве, затем я добавил действие «Решения», в котором параметры, выбранные пользователем, отображаются красным цветом, если ответ неправильный, и зеленым в противном случае. У меня нет проблем с отображением зеленого цвета, поскольку я напрямую вызываю ответ из базы данных и выделяю соответствующим образом.

Но я сталкиваюсь с проблемой при выделении неправильных параметров, выбранных пользователем, поскольку selected_options массив работает не так, как я хочу. Кроме того, я получаю java.lang.ArrayIndexOutOfBoundsException: length=4; index=4 сообщение об ошибке, когда я достигаю нижней части ScrollView в активности solutions, и активность завершается сбоем.

Вот как я объявляю переменную selected_options :

     public static final ArrayList<questionObject> selected_questions = new ArrayList<>();
    public static int[] selected_options;
    public ArrayList<questionObject> resu<
    public ArrayList<questionObject> seen_questions;
    TextView question, option1_text, option2_text, option3_text, option4_text, qCount;
    ConstraintLayout[] options = new ConstraintLayout[4];
    DatabaseReference databaseReference;
    String currentUserID;
    private Dialog loadingDialog;
    
    private int quesNum;
    private int score;
  

Вот как я инициализирую его в onCreate() функции:

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStatusBarGradiant(this);
        setContentView(R.layout.quiz_activity);

        seen_questions = new ArrayList<>();
        result = new ArrayList<>();
        selected_options = new int[5];


        question = findViewById(R.id.question_text);
        qCount = findViewById(R.id.quest_num);
  

Вот как я добавляю выбранные параметры в onClick() метод:

 public void onClick(View view) {

        int selectedOption = 0;

        switch (view.getId()) {

            case R.id.option_1_tile:
                selectedOption = 1;
                break;
            case R.id.option_2_tile:
                selectedOption = 2;
                break;
            case R.id.option_3_tile:
                selectedOption = 3;
                break;
            case R.id.option_4_tile:
                selectedOption = 4;
                break;

            default:

        }

        selected_options[quesNum] = selectedOption;
        checkAnswer(selectedOption, view);
    }
  

И вот как я пытаюсь использовать его в quizAdater :

 class questionAdapter extends BaseAdapter {


    TextView question, option1_text, option2_text, option3_text, option4_text, explanation, source;
    ConstraintLayout[] options = new ConstraintLayout[4];
    private Context context;
    private ArrayList<questionObject> questions = quizActivity.selected_questions;
    private int[] optionsSelected = quizActivity.selected_options;

    public questionAdapter(Context context, ArrayList<questionObject> arrayList) {
        this.context = context;
        this.questions = arrayList;
    }

    @Override
    public int getCount() {
        return questions.size();
    }

    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        convertView = LayoutInflater.from(context).inflate(R.layout.quiz_solutions_row, parent, false);
        question = convertView.findViewById(R.id.question_text);
        option1_text = convertView.findViewById(R.id.option_1_text);
        option2_text = convertView.findViewById(R.id.option_2_text);
        option3_text = convertView.findViewById(R.id.option_3_text);
        option4_text = convertView.findViewById(R.id.option_4_text);
        explanation = convertView.findViewById(R.id.explanation);

        source = convertView.findViewById(R.id.source_button);


        options[0] = convertView.findViewById(R.id.option_1_tile);
        options[1] = convertView.findViewById(R.id.option_2_tile);
        options[2] = convertView.findViewById(R.id.option_3_tile);
        options[3] = convertView.findViewById(R.id.option_4_tile);

        question.setText(questions.get(position).getQuestion());
        option1_text.setText(questions.get(position).getOption1());
        option2_text.setText(questions.get(position).getOption2());
        option3_text.setText(questions.get(position).getOption3());
        option4_text.setText(questions.get(position).getOption4());
        explanation.setText("Explanation: "   questions.get(position).getExplanation());

        source.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent i = new Intent(context, urlActivity.class);
                i.putExtra("url", questions.get(position).getSource());
                i.putExtra("name", "Information Source");
                context.startActivity(i);
            }
        });

        if (optionsSelected[position] != questions.get(position).getAnswer()) {

            options[position].setBackgroundTintList(ColorStateList.valueOf(Color.RED));
        }

        switch (questions.get(position).getAnswer()) {
            case 1:
                options[0].setBackgroundTintList(ColorStateList.valueOf(Color.GREEN));
                break;
            case 2:
                options[1].setBackgroundTintList(ColorStateList.valueOf(Color.GREEN));
                break;
            case 3:
                options[2].setBackgroundTintList(ColorStateList.valueOf(Color.GREEN));
                break;
            case 4:
                options[3].setBackgroundTintList(ColorStateList.valueOf(Color.GREEN));
                break;

        }

        return convertView;
    }
}
  

Вот фиктивный код, запрошенный пользователем:

  1. объявите целочисленную переменную массива selected_options в классе quizActivity

  2. Инициализируйте целочисленный массив в onCreate() методе как selected_options = new int[5];

  3. Добавьте выбранный пользователем вариант (пользователю показывается 5 вопросов, и у каждого есть 4 варианта) как 1 — для варианта A, 2 — для варианта 2 и так далее

  4. В quizAdapter классе инициируйте целочисленный массив optionsSelected и сохраните в нем значения массива переменных selected_options из класса quizActivity, используя private int[] optionsSelected = quizActivity.selected_options;

  5. Если пользователь выбрал неправильную опцию, отобразите выбранную им опцию красным цветом в упражнении решения, используя

    if (optionsSelected[position] != questions.get(position).getAnswer()) {

              options[position].setBackgroundTintList(ColorStateList.valueOf(Color.RED));
         }
      

Я проверил журналы, и переменная quesNum правильно меняется с 0 на 4, и selected_options массив также работает должным образом, поэтому я не могу отладить то, что может быть причиной проблемы

Комментарии:

1. selected_options = new int[4];

2. правильна ли остальная часть реализации для моего варианта использования? И почему int[4] ?

3. У меня есть 5 вопросов за попытку, так что не должно быть [5] ? И это приводит к сбою теста по самому последнему вопросу

4. doing that crashes the quiz on the last question itself какая строка? вы отлаживали?

5. java.lang.ArrayIndexOutOfBoundsException: length=4; index=4 at inspire2connect.inspire2connect.quiz.quizActivity.onClick(quizActivity.java:345) selected_options[quesNum] = selectedOption; в строке onClick() метода, который я привел выше

Ответ №1:

Добавьте проверку перед установкой selectedOption в список, как показано ниже —

 if(quesNum < 4){
    selected_options[quesNum] = selectedOption;
    checkAnswer(selectedOption, view);
}
  

Проверьте, когда и где вы увеличиваете значение quesNum . Попробуйте вывести его значение перед получением индекса из списка. Это 4, поэтому происходит сбой, потому что значение индекса больше размера списка.

Комментарии:

1. не должно ли это быть (quesNum < 5) потому, что у меня всего 5 вопросов, которые нужно показать?

2. Согласно вашим журналам сбоев, происходит сбой для индекса 4. Вот почему я попросил напечатать значение для quesNum. Вы узнаете точное значение и проблему.

3. он регистрируется только как 0, 1, 2, 3, 4. В чем тогда может быть проблема?

4. Теперь проверьте, попробуйте напечатать размер списка selected_options. Если размер списка печатает 5, нам нужно отладить код. Но если размер списка напечатает 4, то сбой очевиден.

5. 2020-09-30 15:27:23.281 32701-32701/inspire2connect.inspire2connect D/Size: Value: 5 2020-09-30 15:27:44.652 32701-32701/inspire2connect.inspire2connect D/Size: Value: 5 2020-09-30 15:27:48.467 32701-32701/inspire2connect.inspire2connect D/Size: Value: 5 2020-09-30 15:27:52.678 32701-32701/inspire2connect.inspire2connect D/Size: Value: 5 2020-09-30 15:27:55.101 32701-32701/inspire2connect.inspire2connect D/Size: Value: 5