Get IndexOutOfBoundsException: индекс: 1, размер: 1 при нажатии на строку - PullRequest
0 голосов
/ 15 сентября 2018

Раньше это работало, но я внес некоторые изменения в свой код, и теперь, когда я удаляю строку из ListView и нажимаю на одну из оставшихся строк, я получаю IndexOutOfBoundsException: Index: 1, Size: 1.

Кажется, что это происходит только тогда, когда осталась одна строка.Если остается более одной строки, эта ошибка не появляется.

enter image description here Изображение выше показывает, что при наличии более одной строки ошибка не возникает.

Я не уверен, почему это произойдет, поскольку ни один из кодов для выбора и удаления строки не изменился.

Я проверил другие сообщения на этом сайте, но ни одна из них, похоже, не былапохоже на то, что я испытываю.

Android IndexOutOfBoundsException: индекс: 1, размер: 1

индекс OutOfBoundException: 1, размер: 1

java jtable removeRow: java.lang.IndexOutOfBoundsException: Index: 1, Size: 1

Я разместил свой код ниже.

Logcat:

java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
        at java.util.ArrayList.get(ArrayList.java:411)
        at ca.rvogl.tpbcui.views.LeagueAdapter$2.onClick(LeagueAdapter.java:116)
        at android.view.View.performClick(View.java:5637)
        at android.view.View$PerformClick.run(View.java:22429)
        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:6119)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

Код для выбора строки в представлении списка:

@Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        League league = leaguesList.get(position);
        int id = league.getId();
        String leagueId = String.valueOf(id);
        holder.id.setText(leagueId);
        holder.name.setText(league.getName());
        holder.basescore.setText(league.getBaseScore());
        holder.basescorepercentage.setText(league.getBaseScorePercentage());
        if (league.getAverage() != "") {
            holder.leagueAverage.setText(String.format("League Avg: %s", league.getAverage()));
        } else {
            holder.leagueAverage.setText(String.format("League Avg: %s", "0"));
        }
        //Formatting And Displaying Timestamp
        holder.timestamp.setText(formatDate(league.getTimestamp()));
        holder.buttonViewOption.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                //creating a popup menu
                PopupMenu popup = new PopupMenu(context, holder.buttonViewOption);
                //inflating menu from xml resource
                popup.inflate(R.menu.league_options_menu);
                //adding click listener
                popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                    @Override
                    public boolean onMenuItemClick(MenuItem item) {
                        switch (item.getItemId()) {
                            case R.id.profile:
                                ((MainActivity) context).showLeagueDialog(true, leaguesList.get(position), position);
                                break;
                            case R.id.delete:
                                ((MainActivity) context).deleteLeague(position);
                                break;
                        }
                        return false;
                    }
                });
                //displaying the popup
                popup.show();

            }
        });
        holder.name.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int leagueId = leaguesList.get(position).getId();
                Intent myIntent = new Intent(context, BowlerActivity.class);
                myIntent.putExtra("leagueId", leagueId);
                context.startActivity(myIntent);
            }
        });
    }

Код для удаления строки:

//Deleting League From SQLite Database And Removing The League Item From The List By Its Position
    public void deleteLeague(int position) {

        Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "Series will be deleted.", Snackbar.LENGTH_LONG)
               .setActionTextColor(Color.YELLOW)
               .setAction("OK", new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        //Deleting The League From The Database
                        db.deleteLeague(leaguesList.get(position));
                        //Removing League From The List
                        leaguesList.remove(position);
                        mAdapter.notifyItemRemoved(position);
                        toggleEmptyLeagues();
                   }
                });
        snackbar.show();
    }

Похоже, ошибка возникает с этой строкойint leagueId = leaguesList.get(position).getId();

Любая помощь в исправлении этой ошибки будет принята с благодарностью.

BowlerActivity.java

public class BowlerActivity extends AppCompatActivity {

    private BowlerAdapter mAdapter;
    private final List<Bowler> bowlersList = new ArrayList<>();
    private TextView noBowlersView;

    private DatabaseHelper db;

    private TextView leagueId;
    private String savedLeagueId;

    private TextView seriesleagueId;
    private String seriesLeagueId;
    private TextView bowlerAverage;
    private TextView bowlerHandicap;
    private String savedBowlerAverage;


    private static final String PREFS_NAME = "prefs";
    private static final String PREF_BLUE_THEME = "blue_theme";
    private static final String PREF_GREEN_THEME = "green_theme";
    private static final String PREF_ORANGE_THEME = "purple_theme";
    private static final String PREF_RED_THEME = "red_theme";
    private static final String PREF_YELLOW_THEME = "yellow_theme";


    @Override protected void onResume() {
        super.onResume();
        db = new DatabaseHelper( this );
        mAdapter.notifyDatasetChanged( db.getAllBowlers( savedLeagueId ) );
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        //Use Chosen Theme
        SharedPreferences preferences = getSharedPreferences( PREFS_NAME, MODE_PRIVATE );
        boolean useBlueTheme = preferences.getBoolean( PREF_BLUE_THEME, false );
        if (useBlueTheme) {
            setTheme( R.style.AppTheme_Blue_NoActionBar );
        }
        boolean useGreenTheme = preferences.getBoolean( PREF_GREEN_THEME, false );
        if (useGreenTheme) {
            setTheme( R.style.AppTheme_Green_NoActionBar );
        }
        boolean useOrangeTheme = preferences.getBoolean( PREF_ORANGE_THEME, false );
        if (useOrangeTheme) {
            setTheme( R.style.AppTheme_Orange_NoActionBar );
        }
        boolean useRedTheme = preferences.getBoolean( PREF_RED_THEME, false );
        if (useRedTheme) {
            setTheme( R.style.AppTheme_Red_NoActionBar );
        }
        boolean useYellowTheme = preferences.getBoolean( PREF_YELLOW_THEME, false );
        if (useYellowTheme) {
            setTheme( R.style.AppTheme_Yellow_NoActionBar );
        }

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bowler);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        Objects.requireNonNull( getSupportActionBar() ).setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDisplayShowHomeEnabled(true);

        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(getApplicationContext(),MainActivity.class));
                finish();
                overridePendingTransition(0, 0);

            }
        });

        savedLeagueId = String.valueOf(getIntent().getIntExtra("leagueId",2));
        leagueId = findViewById(R.id.tvLeagueId);
        bowlerAverage = (TextView) findViewById(R.id.tvBowlerAverage);

                bowlerHandicap = (TextView) findViewById(R.id.tvBowlerHandicap);

        CoordinatorLayout coordinatorLayout = findViewById( R.id.coordinator_layout );
        RecyclerView recyclerView = findViewById( R.id.recycler_view );
        noBowlersView = findViewById(R.id.empty_bowlers_view);

        db = new DatabaseHelper(this);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.add_bowler_fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showBowlerDialog(false, null, -1);
            }
        });

        mAdapter = new BowlerAdapter(this, bowlersList);
        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        //recyclerView.addItemDecoration(new MyDividerItemDecoration(this, LinearLayoutManager.VERTICAL, 16));
        recyclerView.setAdapter(mAdapter);

        toggleEmptyBowlers();
    }

    //Inserting New Bowler In The Database And Refreshing The List
    private void createBowler(String leagueId, String bowlerName) {
        String bowlerAverage = "0";
        //Inserting Bowler In The Database And Getting Newly Inserted Bowler Id
        long id = db.insertBowler(leagueId, bowlerName, bowlerAverage);

        //Get The Newly Inserted Bowler From The Database
        Bowler n = db.getBowler(leagueId);

        if (n != null) {
            //Adding New Bowler To The Array List At Position 0
            bowlersList.add( 0, n );
            //Refreshing The List
            mAdapter.notifyDatasetChanged(db.getAllBowlers(savedLeagueId));
            //mAdapter.notifyDataSetChanged();
            toggleEmptyBowlers();
        }
    }

    //Updating Bowler In The Database And Updating The Item In The List By Its Position
    private void updateBowler(String bowlerName, int position) {
        Bowler n = bowlersList.get(position);

        //Updating Bowler Text
        n.setLeagueId(savedLeagueId);
        n.setName(bowlerName);

        //Updating The Bowler In The Database
        db.updateBowler(n);

        //Refreshing The List
        bowlersList.set(position, n);
        mAdapter.notifyItemChanged(position);

        toggleEmptyBowlers();
    }

    //Deleting Bowler From SQLite Database And Removing The Bowler Item From The List By Its Position
    public void deleteBowler(int position) {

        Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "Series will be deleted.", Snackbar.LENGTH_LONG)
                .setActionTextColor(Color.YELLOW)
                .setAction("OK", new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        //Deleting The Bowler From The Database
                        db.deleteBowler(bowlersList.get(position));
                        //Removing The Bowler From The List
                        bowlersList.remove(position);
                        mAdapter.notifyItemRemoved(position);
                        db.leagueAverageScore(savedLeagueId);
                        toggleEmptyBowlers();
                    }
                });
        snackbar.show();
    }


    //Opens Dialog With Edit/Delete Options

    private void showActionsDialog(final int position) {
        LayoutInflater layoutInflaterAndroid = LayoutInflater.from(getApplicationContext());
        View view = View.inflate(this, R.layout.dialog_options_1, null);

        final AlertDialog.Builder alertDialogBuilderUserInput = new AlertDialog.Builder(new ContextThemeWrapper(BowlerActivity.this, R.style.AppTheme));
        alertDialogBuilderUserInput.setView(view);
        alertDialogBuilderUserInput.setCancelable(true);

        final AlertDialog alertDialog = alertDialogBuilderUserInput.create();

        //Cancel
        final ImageButton cancel_btn = (ImageButton) view.findViewById(R.id.cancel);
        cancel_btn.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                alertDialog.cancel();
            }
        });

        //Edit
        ImageButton edit_btn = (ImageButton) view.findViewById(R.id.edit);
        edit_btn.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                showBowlerDialog(true, bowlersList.get(position), position);
                alertDialog.dismiss();
            }
        });

        ImageButton delete_btn = (ImageButton) view.findViewById(R.id.delete);
        delete_btn.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "Bowler will be deleted.", Snackbar.LENGTH_LONG)
                        .setAction("OK", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                deleteBowler(position);
                            }
                        });

                snackbar.show();
                alertDialog.dismiss();
            }
        });
        Window window = alertDialog.getWindow();
        window.setGravity(Gravity.TOP);
        alertDialog.show();
    }

    //Show Alert Dialog With EditText Options to Enter/Edit A League
    //When shouldUpdate = true, It Will Automatically Display Old Bowler Name And Change The Button Text To UPDATE
    public void showBowlerDialog(final boolean shouldUpdate, final Bowler bowler, final int position) {
        LayoutInflater layoutInflaterAndroid = LayoutInflater.from(getApplicationContext());
        final View view = View.inflate(this, R.layout.dialog_bowler, null);
        AlertDialog.Builder alertDialogBuilderUserInput = new AlertDialog.Builder(new ContextThemeWrapper(BowlerActivity.this, R.style.AppTheme));
        alertDialogBuilderUserInput.setView(view);
        alertDialogBuilderUserInput.setCancelable(true);
        leagueId.setText(savedLeagueId);
        final EditText inputBowlerName = view.findViewById(R.id.etBowlerNameInput);
        TextView dialogTitle = view.findViewById(R.id.dialog_title);
        dialogTitle.setText(!shouldUpdate ? getString(R.string.lbl_new_bowler_title) : getString(R.string.lbl_edit_bowler_title));

        if (shouldUpdate && bowler != null) {
            leagueId.setText(bowler.getLeagueId());
            inputBowlerName.setText(bowler.getName());

        }
        alertDialogBuilderUserInput
                .setCancelable(false)
                .setPositiveButton(shouldUpdate ? "update" : "save", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialogBox, int id) {

                    }
                })
                .setNegativeButton("cancel",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialogBox, int id) {
                                dialogBox.cancel();
                            }
                        });
        ImageView bowlerName = (ImageView) view.findViewById (R.id.ivBowlerName);
        bowlerName.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {

                AlertDialog.Builder bowlerName = new AlertDialog.Builder(BowlerActivity.this);
                bowlerName.setMessage("Enter the name of the bowler to hold your new scores.");
                bowlerName.setCancelable(true);
                bowlerName.create();
                bowlerName.show();
            }
        });

        final AlertDialog alertDialog = alertDialogBuilderUserInput.create();
        alertDialog.show();

        alertDialog.getButton( AlertDialog.BUTTON_POSITIVE).setOnClickListener( new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                //Show Toast Message When No Text Is Entered
                if (TextUtils.isEmpty(inputBowlerName.getText().toString())) {
                    Snackbar.make( view, "Enter Bowler Name", Snackbar.LENGTH_LONG )
                            .setAction( "Action", null ).show();
                    return;
                } else {
                    alertDialog.dismiss();
                }

                //Check If User Is Updating Bowler
                if (shouldUpdate && bowler != null) {

                    //Updating Bowler By Its Id
                    updateBowler(inputBowlerName.getText().toString(), position);

                } else {
                    //Creating New Bowler
                    createBowler(leagueId.getText().toString(), inputBowlerName.getText().toString());

                }
            }
        });
    }

    //Toggling List And Empty Bowler View
    private void toggleEmptyBowlers() {
        //You Can Check bowlerList.size() > 0

        if (db.getBowlersCount() > 0) {
            noBowlersView.setVisibility( View.GONE);
        } else {
            noBowlersView.setVisibility( View.VISIBLE);
        }
    }

    @Override
    public void onRestart() {
        super.onRestart();
        //When BACK BUTTON is pressed, the activity on the stack is restarted
        //Do what you want on the refresh procedure here
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate( R.menu.menu_main, menu );
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            Intent intent = new Intent(this, SettingsActivity.class);
            startActivity(intent);
            overridePendingTransition(0, 0);
            return true;
        }

        return super.onOptionsItemSelected( item );
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);
        //Check If Request Code Is The Same As What Is Passed - Here It Is 1
        if(requestCode==1)
        {
            String savedLeagueId=data.getStringExtra("seriesLeagueId");
            String seriesBowlerId=data.getStringExtra("seriesBowlerId");
            bowlersList.addAll(db.getAllBowlers(savedLeagueId));
        }
    }

    @Override
    public void onBackPressed() {
        startActivity(new Intent(getApplicationContext(),MainActivity.class));
        finish();
        overridePendingTransition(0, 0);
    }
}

Это линия, на которую она жалуется.Это работало отлично, прежде чем я переместить onClick () к адаптеру.

savedLeagueId = String.valueOf(getIntent().getIntExtra("leagueId",2));

Я очень надеюсь, что кто-нибудь может помочь мне решить эту проблему.Я пробовал несколько других подходов из других сообщений stackoverflow, и я до сих пор не могу решить его.

Ответы [ 3 ]

0 голосов
/ 16 сентября 2018

Проблема в том, что представление уже привязано и позиция этого метода:

    holder.name.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {
            int leagueId = leaguesList.get(position).getId(); // here position will still be 1 after deletion
            //...
        }
    });

принадлежит старому индексу. Чтобы исправить это, используйте тот же объект, который вы использовали ранее.

    holder.name.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            int leagueId = league.getId(); //league object will be the same
            //...
        }
    });
0 голосов
/ 16 сентября 2018
mAdapter.notifyItemRemoved(position);

Означает, что адаптер будет сдвигать и анимировать элементы вверх.Тем не менее, элементы не будут перерисованы.

Вы можете наблюдать это, нажав на последний элемент вашего списка после удаления любого элемента: вы должны увидеть тот же сбой.

И нажав налюбой элемент после того, который вы удалили (кроме последнего), в подробном представлении должен отображаться следующий элемент вместо того, на который вы щелкнули.

Проблема в том, что position больше не имеет значения, поскольку индексыбыли изменены.Вместо этого используйте значение для leagueId, которое у вас уже есть в вашей папке.Просто удалите int leagueId, который скрывает String leagueId, и он должен работать как ожидалось.

0 голосов
/ 16 сентября 2018

Это проблема нулевых элементов.Ваш код пытается получить доступ к несуществующему элементному индексу.Запустите ваше приложение в режиме отладки и построчно посмотрите, что происходит.В Android-студии есть отличный встроенный отладчик, поэтому очень легко идти шаг за шагом и смотреть, что происходит с вашими переменными.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...