添加新记录时ListView不刷新

时间:2018-06-06 15:32:10

标签: java android sqlite listview

似乎无法解决这个问题,我已经完成了所有代码而没有任何成功。当我向空列表中添加新的投球手时,它显示正确,当我向列表中添加第二个或更多投球手时,投球手的名称显示为添加的第一个投球手的名称。我在下面列出了几个屏幕截图,以显示我的意思。

enter image description here enter image description here enter image description here enter image description here

显然,这些图像的顺序是从左到右。我也将BowlerActivity包括在这篇文章中。这是我创建和更新新的和现有的保龄球的地方。

private BowlerAdapter mAdapter;
    private List<Bowler> bowlersList = new ArrayList<>();
    private CoordinatorLayout coordinatorLayout;
    private RecyclerView recyclerView;
    private TextView noBowlersView;

    private DatabaseHelper db;

    private TextView leagueId;
    private String savedLeagueId;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bowler);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDisplayShowHomeEnabled(true);

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

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

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

        db = new DatabaseHelper(this);

        bowlersList.addAll(db.getAllBowlers(savedLeagueId));

        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();

        //On Long Click On The RecyclerView Item An Alert Dialog Is Opened With The Option To Choose Edit/Delete
        recyclerView.addOnItemTouchListener(new RecyclerTouchListener(this,
                recyclerView, new RecyclerTouchListener.ClickListener() {
            @Override
            public void onClick(View view, final int position) {

                String seriesLeagueId = bowlersList.get(position).getLeagueId();
                int seriesBowlerId = bowlersList.get(position).getId();
                Intent myIntent = new Intent(BowlerActivity.this, SeriesActivity.class);
                myIntent.putExtra("seriesLeagueId", seriesLeagueId);
                myIntent.putExtra("seriesBowlerId", seriesBowlerId);
                startActivity(myIntent);

            }

            @Override
            public void onLongClick(View view, int position) {
                showActionsDialog(position);
            }
        }));
    }

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

        //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();

            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
    private void deleteBowler(int position) {
        //Deleting The Bowler From The Database
        db.deleteBowler(bowlersList.get(position));

        //Removing The Bowler From The List
        bowlersList.remove(position);
        mAdapter.notifyItemRemoved(position);

        toggleEmptyBowlers();
    }

    //Opens Dialog With Edit/Delete Options
    //Edit - 0
    //Delete - 0
    private void showActionsDialog(final int position) {
        CharSequence colors[] = new CharSequence[]{"Edit", "Delete"};

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Choose option");
        builder.setItems(colors, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (which == 0) {
                    showBowlerDialog(true, bowlersList.get(position), position);
                } else {
                    deleteBowler(position);
                }
            }
        });
        builder.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
    private void showBowlerDialog(final boolean shouldUpdate, final Bowler bowler, final int position) {
        LayoutInflater layoutInflaterAndroid = LayoutInflater.from(getApplicationContext());
        View view = layoutInflaterAndroid.inflate(R.layout.dialog_bowler, null);

        AlertDialog.Builder alertDialogBuilderUserInput = new AlertDialog.Builder(BowlerActivity.this);
        alertDialogBuilderUserInput.setView(view);

        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();
                            }
                        });

        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())) {
                    Toast.makeText(BowlerActivity.this, "Enter Bowler!", Toast.LENGTH_SHORT).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 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) {
            return true;
        }

        return super.onOptionsItemSelected( item );
    }
}

我还包含了包含Bowler方法的DatabaseHelper部分。

public long insertBowler(String leagueId, String bowlerName) {
        //Get Writable Database That We Want To Write Data Too
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        //`id` and `timestamp` Will Be Inserted Automatically
        values.put(Bowler.COLUMN_LEAGUE_ID, leagueId);
        values.put(Bowler.COLUMN_NAME, bowlerName);

         //Insert Row
        long id = db.insert( Bowler.TABLE_NAME, null, values );

        //Close Database Connection
        db.close();

        //Return Newly Inserted Row Id
        return id;
    }

    public Bowler getBowler(String leagueId) {
        //Get Readable Database If We Are Not Inserting Anything
        SQLiteDatabase db = this.getReadableDatabase();

        Cursor cursor = db.query(Bowler.TABLE_NAME,
                new String[]{Bowler.COLUMN_ID, Bowler.COLUMN_LEAGUE_ID, Bowler.COLUMN_NAME, Bowler.COLUMN_TIMESTAMP},
                Bowler.COLUMN_LEAGUE_ID + "=?",
                new String[]{String.valueOf(leagueId)}, null, null, null, null);

        if (cursor.moveToFirst()) {

            //Prepare Bowler Object
        Bowler bowler = new Bowler(
                cursor.getInt(cursor.getColumnIndex(Bowler.COLUMN_ID)),
                cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_LEAGUE_ID)),
                cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_NAME)),
                cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_TIMESTAMP)));

        //Close Database Connection
        cursor.close();
        return bowler;
    } else {return null;}
}
    public List<Bowler> getAllBowlers(String leagueId) {
        List<Bowler> bowlers = new ArrayList<>();

        //Select All Query
        String selectQuery = "SELECT  * FROM " + Bowler.TABLE_NAME + " WHERE " + Bowler.COLUMN_LEAGUE_ID + " = '" + leagueId + "'" + " ORDER BY " +
                Bowler.COLUMN_TIMESTAMP + " DESC";

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        //Looping Through All Rows And Adding To The List
        if (cursor.moveToFirst()) {
            do {
                Bowler bowler = new Bowler();
                bowler.setId(cursor.getInt(cursor.getColumnIndex(Bowler.COLUMN_ID)));
                bowler.setLeagueId(cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_LEAGUE_ID)));
                bowler.setName(cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_NAME)));
                bowler.setTimestamp(cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_TIMESTAMP)));
                bowlers.add(bowler);
            } while (cursor.moveToNext());
        }
        cursor.close();
        //Close Database Connection
        db.close();

        //Return Bowlers List
        return bowlers;
    }

    public int getBowlersCount() {
        String countQuery = "SELECT  * FROM " + Bowler.TABLE_NAME;
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(countQuery, null);

        int count = cursor.getCount();
        cursor.close();

        //Return The Count
        return count;
    }

    public int updateBowler(Bowler bowler) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(Bowler.COLUMN_LEAGUE_ID, bowler.getLeagueId());
        values.put(Bowler.COLUMN_NAME, bowler.getName());

        //Updating Row
        return db.update(Bowler.TABLE_NAME, values, Bowler.COLUMN_ID + " = ?",
                new String[]{String.valueOf(bowler.getId())});
    }

    public void deleteBowler(Bowler bowler) {
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete( Bowler.TABLE_NAME, Bowler.COLUMN_ID + " = ?",
                new String[]{String.valueOf( bowler.getId())});
        db.close();
    }

如果需要我也发布了BowlerAdapter代码。

public class BowlerAdapter extends RecyclerView.Adapter<BowlerAdapter.MyViewHolder> {

    private Context context;
    private List<Bowler> bowlersList;

    public class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView bowlerLeagueId;
        public TextView name;
        public TextView timestamp;

        public MyViewHolder(View view) {
            super(view);
            bowlerLeagueId = view.findViewById( R.id.tvLeagueId);
            name = view.findViewById(R.id.tvBowlerName );
            timestamp = view.findViewById(R.id.timestamp);
        }
    }


    public BowlerAdapter(Context context, List<Bowler> bowlersList) {
        this.context = context;
        this.bowlersList = bowlersList;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.listview_bowler, parent, false);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        Bowler bowler = bowlersList.get(position);

        holder.bowlerLeagueId.setText(bowler.getLeagueId());
        holder.name.setText(bowler.getName());

        //Formatting And Displaying Timestamp
        holder.timestamp.setText(formatDate(bowler.getTimestamp()));
    }

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

    //Formatting TimeStamp to 'EEE MMM dd yyyy (HH:mm:ss)'
    //Input  : 2018-05-23 9:59:01
    //Output : Wed May 23 2018 (9:59:01)
    private String formatDate(String dateStr) {
        try {
            SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date = fmt.parse(dateStr);
            SimpleDateFormat fmtOut = new SimpleDateFormat("EEE MMM dd yyyy (HH:mm:ss)");
            return fmtOut.format(date);
        } catch (ParseException e) { }

        return "";
    }

我确信它是非常明显的,但我一直在查看代码几个小时,我只是没有看到问题。

任何帮助都将不胜感激。

我已按照您的指示修改了我的代码,但是当我添加一个新的投球手时,屏幕显示为空白,直到我离开BowlerActivity并返回其中,此时列表已更新。

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

        //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(bowlersList);

            toggleEmptyBowlers();
        }
    }

BowlerAdapter notifyDataSetChanged方法

private List<Bowler> bowlersList;

    public void notifyDataSetChanged(List<Bowler> newbowlersList) {
        bowlersList.clear();
        bowlersList.addAll( newbowlersList );
        super.notifyDataSetChanged();
    }

enter image description here enter image description here enter image description here

调试日志

this = {BowlerActivity@5027} 
leagueId = "1"
bowlerName = "Robert"
id = 6
n = {Bowler@5032} 
 id = 1
 league_id = "1"
 name = "b1"
 timestamp = "2018-06-07 20:03:19"
 shadow$_klass_ = {Class@4839} "class ca.rvogl.tpbcui.database.models.Bowler"
 shadow$_monitor_ = -2106571381
mAdapter = {BowlerAdapter@5033} 
 bowlersList = {ArrayList@5037}  size = 0
 mHasStableIds = false
 mObservable = {RecyclerView$AdapterDataObservable@5088} 
 shadow$_klass_ = {Class@4930} "class ca.rvogl.tpbcui.views.BowlerAdapter"
 shadow$_monitor_ = -2088753560

log.d log file snippet

06-08 13:00:53.807 29879-29879/ca.rvogl.tpbcui D/INSERTBOWLER: Number of bowlers in db = 4
06-08 13:00:53.814 29879-29884/ca.rvogl.tpbcui I/art: Do partial code cache collection, code=30KB, data=29KB
06-08 13:00:53.815 29879-29884/ca.rvogl.tpbcui I/art: After code cache collection, code=30KB, data=29KB
    Increasing code cache capacity to 128KB
06-08 13:00:53.815 29879-29895/ca.rvogl.tpbcui D/EGL_emulation: eglMakeCurrent: 0x9e6fa300: ver 3 0 (tinfo 0xa068a610)
06-08 13:00:53.831 29879-29879/ca.rvogl.tpbcui W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
06-08 13:01:00.552 29879-29895/ca.rvogl.tpbcui D/EGL_emulation: eglMakeCurrent: 0x9e6fa300: ver 3 0 (tinfo 0xa068a610)
06-08 13:01:02.336 29879-29895/ca.rvogl.tpbcui D/EGL_emulation: eglMakeCurrent: 0x9e6fa300: ver 3 0 (tinfo 0xa068a610)
06-08 13:01:04.023 29879-29895/ca.rvogl.tpbcui D/EGL_emulation: eglMakeCurrent: 0x9e6fa300: ver 3 0 (tinfo 0xa068a610)
06-08 13:01:04.040 29879-29895/ca.rvogl.tpbcui D/EGL_emulation: eglMakeCurrent: 0x9e6fa300: ver 3 0 (tinfo 0xa068a610)
06-08 13:01:04.050 29879-29895/ca.rvogl.tpbcui D/EGL_emulation: eglMakeCurrent: 0x9e6fa300: ver 3 0 (tinfo 0xa068a610)
06-08 13:01:04.059 29879-29895/ca.rvogl.tpbcui D/EGL_emulation: eglMakeCurrent: 0x9e6fa300: ver 3 0 (tinfo 0xa068a610)
06-08 13:01:04.534 29879-29895/ca.rvogl.tpbcui D/EGL_emulation: eglMakeCurrent: 0x9e6fa300: ver 3 0 (tinfo 0xa068a610)
06-08 13:01:04.542 29879-29895/ca.rvogl.tpbcui D/EGL_emulation: eglMakeCurrent: 0x9e6fa300: ver 3 0 (tinfo 0xa068a610)
06-08 13:01:05.034 29879-29895/ca.rvogl.tpbcui D/EGL_emulation: eglMakeCurrent: 0x9e6fa300: ver 3 0 (tinfo 0xa068a610)
06-08 13:01:11.363 29879-29895/ca.rvogl.tpbcui D/EGL_emulation: eglMakeCurrent: 0x9e6fa300: ver 3 0 (tinfo 0xa068a610)
06-08 13:01:11.373 29879-29879/ca.rvogl.tpbcui D/INSERTBOWLER: Number of bowlers in db = 5
06-08 13:01:11.380 29879-29895/ca.rvogl.tpbcui D/EGL_emulation: eglMakeCurrent: 0x9e6fa300: ver 3 0 (tinfo 0xa068a610)
06-08 13:01:11.393 29879-29879/ca.rvogl.tpbcui W/IInputConnectionWrapper: finishComposingText on inactive InputConnection

1 个答案:

答案 0 :(得分:1)

我认为您的问题是您没有更新适配器中的实际源列表。

解决方案可以是向BowlerAdapter添加一个方法,例如: -

public void notifyDatasetChanged(List<Bowler> newbowlerlist) {
    bowlersList.clear();
    bowlersList.addAll(newbowlerlist);
    super.notifyDataSetChanged();
}

然后使用这个新方法,传递修改后的bowlerlist,而不是stock notifyDatasetChanged方法。

e.g。而不是: -

    if (n != null) {
        //Adding New Bowler To The Array List At Position 0
        bowlersList.add(0, n);

        //Refreshing The List
        mAdapter.notifyDataSetChanged();

        toggleEmptyBowlers();
    }

使用: -

    if (n != null) {
        //Adding New Bowler To The Array List At Position 0
        bowlersList.add(0, n);

        //Refreshing The List
        mAdapter.notifyDataSetChanged(bowlerList);

        toggleEmptyBowlers();
    }

根据您使用上述代码,获得以下结果: -

初始显示

enter image description here

  • 最初在App启动时添加了2个Bowlers。
  • 添加了按钮而非代码所有对话框处理(因此,如果EditText不是空白,则单击按钮将添加新的投球手。)

添加新的保龄球后

新增一名投球手: -

  1. 在EditText中输入Howard。
  2. 点击添加保龄球按钮。
  3. 刷新列表,显示添加的Bowler。
  4. : -

    enter image description here

    补充评论: -

      

    好的,插入正常(您可以删除更改)。现在做   以下对getAllBowlers方法的更改(1写入   selectQuery sql到日志,2写入检索到的行数   log和3将保龄球ArrayList的大小写入   日志)。运行并报告或修复。

    public List<Bowler> getAllBowlers(String leagueId) {
        List<Bowler> bowlers = new ArrayList<>();
    
        //Select All Query
        String selectQuery = "SELECT  * FROM " + Bowler.TABLE_NAME + " WHERE " + Bowler.COLUMN_LEAGUE_ID + " = '" + leagueId + "'" + " ORDER BY " +
                Bowler.COLUMN_TIMESTAMP + " DESC";
    
        Log.d("GETALLBOWLERS-SQL","SQL used = >>>>" +selectQuery + "<<<<");
    
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);
    
        Log.d("GETALLBOWLERS-CNT","Number of rows retrieved = " + String.valueOf(cursor.getCount()));
    
    
        //Looping Through All Rows And Adding To The List
        if (cursor.moveToFirst()) {
            do {
                Bowler bowler = new Bowler();
                bowler.setId(cursor.getInt(cursor.getColumnIndex(Bowler.COLUMN_ID)));
                bowler.setLeagueId(cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_LEAGUE_ID)));
                bowler.setName(cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_NAME)));
                bowler.setTimestamp(cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_TIMESTAMP)));
                bowlers.add(bowler);
            } while (cursor.moveToNext());
        }
        cursor.close();
        //Close Database Connection
        db.close();
        Log.d("GETALLBOWLERS-CNT","Number of elements in bowlerslist = " + String.valueOf(bowlers.size()));
    
        //Return Bowlers List
        return bowlers;
    }
    

    工作示例

    我实际上无法确定您的问题,但我确实认为它与原始答案有关,因为适配器使用投球手列表的副本工作/与投球手列表不同列表传递给它。因此,更改活动中的投球手清单不会更改适配器中的投球手清单。因此,在更改保龄球列表后发出onNotifyDatasetChanged是对适配器说你已经更改了适配器中的列表(即它的副本,它没有被更改)。 / p>

    因此,必须更改投球手清单上的副本,然后才能发出onNotifyDatasetChanged。我的猜测是你没有正确实现上述目的。

    因此我实际上重新创建了您的代码,并且有一个适用的版本: -

    • 不使用操作栏,而是使用按钮添加投球手。
    • 而不是由其他活动调用并从Intent Extra获取LeagueID,而且UnionID是硬编码的。
    • 为方便起见,ClickListener界面包含在活动中。

    活动(我称之为BowlerActivity)

    public class BowlerActivity extends AppCompatActivity {
    
        private BowlerAdapter mAdapter;
        private List<Bowler> bowlersList = new ArrayList<>();
        private RecyclerView recyclerView;
        private DatabaseHelper db;
        private Button addbowler;
        private EditText newbowler;
        private TextView leagueId, noBowlersView;
        private String savedLeagueId;
        Context mContext;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mContext = this;
            addbowler = this.findViewById(R.id.addbowler); // For testing
            leagueId = this.findViewById(R.id.tvLeagueId);
            noBowlersView = this.findViewById(R.id.noBowlersView);
            recyclerView = this.findViewById(R.id.recycler_view);
            db = new DatabaseHelper(this);
    
            savedLeagueId = "0"; //<<<< HARD CODED rather than get from IntentExtra
            leagueId.setText(savedLeagueId);
            bowlersList = db.getAllBowlers(leagueId.getText().toString());
            RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this);
            mAdapter = new BowlerAdapter(this,bowlersList);
            recyclerView.setLayoutManager(mLayoutManager);
            recyclerView.setItemAnimator(new DefaultItemAnimator());
            //recyclerView.addItemDecoration(new MyDividerItemDecoration(this, LinearLayoutManager.VERTICAL, 16));
            recyclerView.setAdapter(mAdapter);
    
            addbowler.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    showBowlerDialog(false, null, -1);
                }
            });
    
            recyclerView.addOnItemTouchListener(new RecyclerTouchListener(this, recyclerView, new ClickListener() {
                @Override
                public void onClick(View view, int position) {
                    Toast.makeText(mContext,"You clicked me", Toast.LENGTH_SHORT).show();
                }
    
                @Override
                public void onLongClick(View view, int position) {
                    Toast.makeText(mContext,"You long clicked me", Toast.LENGTH_SHORT).show();
                    showActionsDialog(position);
    
                }
            }));
        }
    
        //Opens Dialog With Edit/Delete Options
        //Edit - 0
        //Delete - 0
        private void showActionsDialog(final int position) {
            CharSequence colors[] = new CharSequence[]{"Edit", "Delete"};
    
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("Choose option");
            builder.setItems(colors, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    if (which == 0) {
                        showBowlerDialog(true, bowlersList.get(position), position);
                    } else {
                        deleteBowler(position);
                    }
                }
            });
            builder.show();
        }
    
        //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);
            }
        }
    
        //Inserting New Bowler In The Database And Refreshing The List
        private void createBowler(String leagueId,  String bowlerName) {
            //Inserting Bowler In The Database And Getting Newly Inserted Bowler Id
            long id = db.insertBowler(leagueId, bowlerName);
    
            //Get The Newly Inserted Bowler From The Database
           bowlersList = db.getAllBowlers(leagueId);
           mAdapter.notifyDatasetChanged(bowlersList);
           //mAdapter.notifyDataSetChanged();
        }
    
        //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); //<<<<< does not change the bowlerlist in the adapter
            //mAdapter.notifyItemChanged(position); // Saying that nothing has changed
            mAdapter.notifyDatasetChanged(db.getAllBowlers(savedLeagueId)); //<<<<< rebuilds adapter bowler list
            toggleEmptyBowlers();
        }
    
        //Deleting Bowler From SQLite Database And Removing The Bowler Item From The List By Its Position
        private void deleteBowler(int position) {
            //Deleting The Bowler From The Database
            db.deleteBowler(bowlersList.get(position));
    
    
            //Removing The Bowler From The List
            bowlersList.remove(position);
            //mAdapter.notifyItemRemoved(position); // Saying that nothing has changed
            mAdapter.notifyDatasetChanged(db.getAllBowlers(savedLeagueId));
            toggleEmptyBowlers();
        }
    
        public interface ClickListener{
            void onClick(View view,int position);
            void onLongClick(View view,int position);
        }
    
        //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
        private void showBowlerDialog(final boolean shouldUpdate, final Bowler bowler, final int position) {
            LayoutInflater layoutInflaterAndroid = LayoutInflater.from(getApplicationContext());
            View view = layoutInflaterAndroid.inflate(R.layout.dialog_bowler, null);
    
            AlertDialog.Builder alertDialogBuilderUserInput = new AlertDialog.Builder(BowlerActivity.this);
            alertDialogBuilderUserInput.setView(view);
    
            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();
                                }
                            });
    
            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())) {
                        Toast.makeText(BowlerActivity.this, "Enter Bowler!", Toast.LENGTH_SHORT).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());
                    }
                }
            });
        }
    }
    
    • 真正唯一的变化是使用onNotifyDatasetChanged(List<Bowler>)方法而不是库存onNotifyDatabsetChanged()

    BowlerAdapter

    public class BowlerAdapter extends RecyclerView.Adapter<BowlerAdapter.MyViewHolder> {
    
        private Context context;
        private List<Bowler> bowlersList;
    
        public class MyViewHolder extends RecyclerView.ViewHolder {
            public TextView bowlerLeagueId;
            public TextView name;
            public TextView timestamp;
    
    
            public MyViewHolder(View view) {
                super(view);
                bowlerLeagueId = view.findViewById(R.id.tvLeagueId);
                name = view.findViewById(R.id.tvBowlerName);
                timestamp = view.findViewById(R.id.timestamp);
            }
        }
    
    
        public BowlerAdapter(Context context, List<Bowler> bowlersList) {
            this.context = context;
            this.bowlersList = bowlersList;
        }
    
        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            int fakeid = android.R.layout.simple_list_item_1;
            int realid = R.layout.listview_boweler;
    
            View itemView = LayoutInflater.from(parent.getContext())
                    .inflate(realid, parent, false);
    
            return new MyViewHolder(itemView);
        }
    
        @Override
        public void onBindViewHolder(MyViewHolder holder, int position) {
            Bowler bowler = bowlersList.get(position);
    
            holder.bowlerLeagueId.setText(bowler.getLeagueId());
            holder.name.setText(bowler.getName());
    
            //Formatting And Displaying Timestamp
            holder.timestamp.setText(formatDate(bowler.getTimestamp()));
        }
    
        @Override
        public int getItemCount() {
            return bowlersList.size();
        }
    
        //<<<<<<<<<< Added >>>>>>>>>>
        // This will get the actual bowler from the list
        public Bowler getItemAtPosition(int position) {
            return bowlersList.get(position);
        }
    
        //Formatting TimeStamp to 'EEE MMM dd yyyy (HH:mm:ss)'
        //Input  : 2018-05-23 9:59:01
        //Output : Wed May 23 2018 (9:59:01)
        private String formatDate(String dateStr) {
            try {
                SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date date = fmt.parse(dateStr);
                SimpleDateFormat fmtOut = new SimpleDateFormat("EEE MMM dd yyyy (HH:mm:ss)");
                return fmtOut.format(date);
            } catch (ParseException e) {
            }
            return "";
        }
    
        public void notifyDatasetChanged(List<Bowler> newbowlerlist) {
            bowlersList.clear();
            bowlersList.addAll(newbowlerlist);
            super.notifyDataSetChanged();
        }
    }
    
    • 注意 notifyDatasetChanged(List<Bowler)方法,这会获取更改的保龄球列表并重建适用的适配器副本,然后调用适配器&#39; s notfiydatasetChanged方法。

    • 已添加但未使用的是getItemAtPosition方法,该方法可用于在给定位置处从适配器返回投球手(这可用于规避更改活动&#39; s圆顶清单的副本)

    DatabaseHelper

    这只包括一些更改,记录了一些信息,但没有改变(尽管添加了一些丢失的代码)。

    public class DatabaseHelper extends SQLiteOpenHelper {
    
        public static final String DBNAME = "leagueapp.db";
        public static final int DBVERSION = 1;
    
        SQLiteDatabase mDB;
    
        public DatabaseHelper(Context context) {
            super(context, DBNAME, null, DBVERSION);
            mDB = this.getWritableDatabase();
        }
    
        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(Bowler.CRTSQL);
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    
        }
    
        public long insertBowler(String leagueId, String bowlerName) {
            //Get Writable Database That We Want To Write Data Too
            SQLiteDatabase db = this.getWritableDatabase();
    
            Log.d("INSERTBOWLER","Number of bowlers in db = " + String.valueOf(DatabaseUtils.queryNumEntries(db,Bowler.TABLE_NAME)));
    
            ContentValues values = new ContentValues();
            //`id` and `timestamp` Will Be Inserted Automatically
            values.put(Bowler.COLUMN_LEAGUE_ID, leagueId);
            values.put(Bowler.COLUMN_NAME, bowlerName);
    
            //Insert Row
            long id = db.insertOrThrow( Bowler.TABLE_NAME, null, values );
    
            //Close Database Connection
            db.close();
    
            //Return Newly Inserted Row Id
            return id;
        }
    
        public Bowler getBowler(String leagueId) {
            //Get Readable Database If We Are Not Inserting Anything
            SQLiteDatabase db = this.getReadableDatabase();
    
            Cursor cursor = db.query(Bowler.TABLE_NAME,
                    new String[]{Bowler.COLUMN_ID, Bowler.COLUMN_LEAGUE_ID, Bowler.COLUMN_NAME, Bowler.COLUMN_TIMESTAMP},
                    Bowler.COLUMN_LEAGUE_ID + "=?",
                    new String[]{String.valueOf(leagueId)}, null, null, null, null);
    
            if (cursor.moveToFirst()) {
    
                //Prepare Bowler Object
                Bowler bowler = new Bowler(
                        cursor.getLong(cursor.getColumnIndex(Bowler.COLUMN_ID)),
                        cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_LEAGUE_ID)),
                        cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_NAME)),
                        cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_TIMESTAMP)));
    
                //Close Database Connection
                cursor.close();
                return bowler;
            } else {return null;}
        }
        public List<Bowler> getAllBowlers(String leagueId) {
            List<Bowler> bowlers = new ArrayList<>();
    
            //Select All Query
            String selectQuery = "SELECT  * FROM " + Bowler.TABLE_NAME + " WHERE " + Bowler.COLUMN_LEAGUE_ID + " = '" + leagueId + "'" + " ORDER BY " +
                    Bowler.COLUMN_TIMESTAMP + " DESC";
    
            Log.d("GETALLBOWLERS-SQL","SQL used = >>>>" +selectQuery + "<<<<");
    
            SQLiteDatabase db = this.getWritableDatabase();
            Cursor cursor = db.rawQuery(selectQuery, null);
    
            Log.d("GETALLBOWLERS-CNT","Number of rows retrieved = " + String.valueOf(cursor.getCount()));
    
    
            //Looping Through All Rows And Adding To The List
            if (cursor.moveToFirst()) {
                do {
                    Bowler bowler = new Bowler();
                    bowler.setId(cursor.getInt(cursor.getColumnIndex(Bowler.COLUMN_ID)));
                    bowler.setLeagueId(cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_LEAGUE_ID)));
                    bowler.setName(cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_NAME)));
                    bowler.setTimestamp(cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_TIMESTAMP)));
                    bowlers.add(bowler);
                } while (cursor.moveToNext());
            }
            cursor.close();
            //Close Database Connection
            db.close();
            Log.d("GETALLBOWLERS-CNT","Number of elements in bowlerslist = " + String.valueOf(bowlers.size()));
    
            //Return Bowlers List
            return bowlers;
        }
    
        public int getBowlersCount() {
            String countQuery = "SELECT  * FROM " + Bowler.TABLE_NAME;
            SQLiteDatabase db = this.getReadableDatabase();
            Cursor cursor = db.rawQuery(countQuery, null);
    
            int count = cursor.getCount();
            cursor.close();
    
            //Return The Count
            return count;
        }
    
        public int updateBowler(Bowler bowler) {
            SQLiteDatabase db = this.getWritableDatabase();
    
            ContentValues values = new ContentValues();
            values.put(Bowler.COLUMN_LEAGUE_ID, bowler.getLeagueId());
            values.put(Bowler.COLUMN_NAME, bowler.getName());
    
            //Updating Row
            return db.update(Bowler.TABLE_NAME, values, Bowler.COLUMN_ID + " = ?",
                    new String[]{String.valueOf(bowler.getId())});
        }
    
        public void deleteBowler(Bowler bowler) {
            SQLiteDatabase db = this.getWritableDatabase();
            db.delete( Bowler.TABLE_NAME, Bowler.COLUMN_ID + " = ?",
                    new String[]{String.valueOf( bowler.getId())});
            db.close();
        }
    
        public int deleteBowlerChecked(Bowler bowler) {
            SQLiteDatabase db = this.getWritableDatabase();
            Log.d("DELETEBOWLER","Attempting to DELETE bowler " + bowler.getName());
            int rv = db.delete(Bowler.TABLE_NAME,Bowler.COLUMN_ID + "=?",
                    new String[]{String.valueOf(bowler.getId())});
            if (rv < 1) {
                Log.d("DELETEBOWLER", "Bowler with an id of " + String.valueOf(bowler.getId()) + " was not deleted, as it didn't exist.");
            }
            return rv;
        }
    }
    

    RecyclerTouchListener

    这个补充说,它可能与你的相同或不同。

    public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener{
    
        private BowlerActivity.ClickListener clicklistener;
        private GestureDetector gestureDetector;
    
        public RecyclerTouchListener(Context context, final RecyclerView recycleView, final BowlerActivity.ClickListener clicklistener){
    
            this.clicklistener=clicklistener;
            gestureDetector=new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){
                @Override
                public boolean onSingleTapUp(MotionEvent e) {
                    return true;
                }
    
                @Override
                public void onLongPress(MotionEvent e) {
                    View child=recycleView.findChildViewUnder(e.getX(),e.getY());
                    if(child!=null && clicklistener!=null){
                        clicklistener.onLongClick(child,recycleView.getChildAdapterPosition(child));
                    }
                }
            });
        }
    
        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
            View child=rv.findChildViewUnder(e.getX(),e.getY());
            if(child!=null && clicklistener!=null && gestureDetector.onTouchEvent(e)){
                clicklistener.onClick(child,rv.getChildAdapterPosition(child));
            }
    
            return false;
        }
    
        @Override
        public void onTouchEvent(RecyclerView rv, MotionEvent e) {
    
        }
    
        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
    
        }
    
    }
    

    结果/测试

    初始屏幕(空数据库): -

    enter image description here

    点击添加保龄球按钮: -

    enter image description here

    Bowler B1输入并保存点击: -

    enter image description here

    更多Bowlers补充说: -

    enter image description here

    Bowler B5更新: -

    enter image description here

    保龄球B1和B6被删除: -

    enter image description here