Can't seem to figure this out, I have gone through all the code without any success. When I add a new bowler to an empty list it appears correctly, when I add a second or more bowlers to the list, the name of the bowler shows up as the name of the first bowler added. I have included several screenshots below to show what I mean.
Obviously the order of these images goes left to right. I have include my BowlerActivity to this post as well. This is where I am creating and updating new and existing bowlers.
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 );
}
}
I have also include the DatabaseHelper portion that contains the Bowler methods.
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();
}
And just in case its required I have posted the BowlerAdapter code as well.
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 "";
}
I am sure its is something very obvious, but I have been looking at the code for a few hours and I just don't see the issue.
Any assistance would be appreciated.
I have amended my code as you indicated, but when I add a new bowler now the screen comes back blank until I leave the BowlerActivity and come back into it, at this point the list has been updated.
//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 method
private List<Bowler> bowlersList;
public void notifyDataSetChanged(List<Bowler> newbowlersList) {
bowlersList.clear();
bowlersList.addAll( newbowlersList );
super.notifyDataSetChanged();
}
Debugging Logs
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
I believe that your issue is that you are not updating the actual source List within the adapter.
Reading Is Java “pass-by-reference” or “pass-by-value”?
may explain.
A resolution could be to be add a method to the BowlerAdapter e.g :-
public void notifyDatasetChanged(List<Bowler> newbowlerlist) {
bowlersList.clear();
bowlersList.addAll(newbowlerlist);
super.notifyDataSetChanged();
}
And to then use this new method, passing the amended bowlerlist, rather than the stock notifyDatasetChanged method.
e.g. instead of :-
if (n != null) {
//Adding New Bowler To The Array List At Position 0
bowlersList.add(0, n);
//Refreshing The List
mAdapter.notifyDataSetChanged();
toggleEmptyBowlers();
}
use :-
if (n != null) {
//Adding New Bowler To The Array List At Position 0
bowlersList.add(0, n);
//Refreshing The List
mAdapter.notifyDataSetChanged(bowlerList);
toggleEmptyBowlers();
}
Based upon you code using the above, the following results are obtained:-
Initial Display
2 Bowlers initially added when App starts.
Added button rather than code all the dialog handling (so clicking the button will add a new bowler, if the EditText isn't blank).
After Adding new Bowler
A new bowler was added by :-
Entering Howard in the EditText.
Clicking the Add Bowler button.
the List is refreshed displaying the added Bowler.
:-
Addition re comment :-
OK, insert is happening OK (you can remove the changes). Now make the
following changes to the getAllBowlers method (1 write the
selectQuery sql to the log, 2 write the number of rows retrieved to
the log and 3 write the size of the bowlers ArrayList to the
log). Run and report or fix.
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;
}
Working Example
I can't actually pinpoint your issue, although I do believe it's related to the original answer in that the Adapter works on/with a copy of of the bowler list, which is different to the bowler list passed to it. As such changing the bowlerlist in the activity does not change the bowlerlist in the adapter. As such issuing a onNotifyDatasetChanged after changing the bowlerlist is saying to the adapter that you've change the list in the adapter (i.e it's copy, which hasn't been changed).
As such the copy on the bowler list has to be changed and then the onNotifyDatasetChanged should be issued. My guess is that you didn't correctly implement the above.
As such I have virtually re-created your code and have a version that works :-
Instead of using an action bar a button is used to add a bowler.
Instead of this being invoked by anther activity and getting the LeagueID from the Intent Extra, the LeagueID is hard coded.
the ClickListener interface is included within the activity for my convenience.
The activity (I've called it 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());
}
}
});
}
}
really the only change is using the onNotifyDatasetChanged(List<Bowler>) method rather than the stock 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();
}
}
Note the notifyDatasetChanged(List<Bowler) method, this takes the changed bowler list and rebuilds the adapter's copy that it works with and then calls the adapter's notfiydatasetChanged method.
Added but not used is the getItemAtPosition method that can be used to return the bowler from the adapter at the given position (this could be used to circumvent altering the activity's copy of the bowlerlist).
DatabaseHelper
This just includes some changes that log's some information but is otherwise unchanged (although some missing code was added).
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
This wad added, it may or may not be the same as yours.
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) {
}
}
Results/Testing
Initial Screen (empty db) :-
Add Bowler Button clicked :-
Bowler B1 entered and Save clicked :-
More Bowlers added :-
Bowler B5 updated :-
Bowlers B1 and B6 deleted :-
Related
I have a list of Leagues that that I want to display the number of bowlers for in each entry. For Example:
I want to display a count of the number of bowlers in each list under each League name in the list. For Example:
This is meant to be a quick view about each League.
I tried to accomplish this with the following code:
DatabaseHelper
//Getting Number of Bowlers in League
public String leagueBowlerCount(String leagueId)
{
SQLiteDatabase db = this.getReadableDatabase();
String countQuery = "SELECT * FROM " + Bowler.TABLE_NAME + " WHERE " + Bowler.COLUMN_LEAGUE_ID + " = '" + leagueId + "'";
Cursor cursor = db.rawQuery(countQuery, null);
int count = 0;
if(null != cursor)
if(cursor.getCount() > 0){
cursor.moveToFirst();
count = cursor.getInt(0);
}
cursor.close();
db.close();
return String.valueOf(count);
}
League Adapter
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView id;
public TextView name;
public TextView baseScore;
public TextView basePercentage;
public TextView bowlerCount;
TextView timestamp;
public TextView buttonViewOption;
MyViewHolder(View view) {
super(view);
if (!(itemView instanceof AdView)) {
id = view.findViewById( R.id.tvLeagueId);
name = view.findViewById(R.id.tvLeagueName );
baseScore = view.findViewById( R.id.tvBaseScore);
basePercentage = view.findViewById(R.id.tvBaseScorePercentage);
bowlerCount = view.findViewById(R.id.tvNumberOfBowlers);
timestamp = view.findViewById(R.id.timestamp);
buttonViewOption = view.findViewById(R.id.buttonViewOptions);
}
}
}
public LeagueAdapter(Context context, List<League> leaguesList) {
this.context = context;
this.leaguesList = leaguesList;
mainActivity = (Activity) context;
inflater = LayoutInflater.from(context);
}
public LeagueAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
AdView adview;
MyViewHolder holder;
if (viewType == AD_TYPE) {
adview = new AdView(mainActivity);
adview.setAdSize( AdSize.BANNER);
// this is the good adview
adview.setAdUnitId(mainActivity.getString(R.string.admob_ad_id));
float density = mainActivity.getResources().getDisplayMetrics().density;
int height = Math.round(AdSize.BANNER.getHeight() * density);
AbsListView.LayoutParams params = new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, height);
adview.setLayoutParams(params);
// dont use below if testing on a device
// follow https://developers.google.com/admob/android/quick-start?hl=en to setup testing device
AdRequest request = new AdRequest.Builder().build();
adview.loadAd(request);
holder = new MyViewHolder(adview);
}else{
View view = inflater.inflate(R.layout.listview_league, parent, false);
holder = new MyViewHolder(view);
}
return holder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
if(position % 10 != 5) {
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.getBasisScore());
holder.basePercentage.setText(league.getBaseScorePercentage());
holder.bowlerCount.setText(db.leagueBowlerCount(leagueId));
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:
//Log.d("leagueId", String.valueOf(position));
//int leagueId = league.getId();
((MainActivity) context).openDialog(true, leaguesList.get(position), position);
break;
case R.id.delete:
((MainActivity) context).deleteLeague(position);
break;
}
return false;
}
});
//displaying the popup
popup.show();
}
});
}
}
I have been messing around with this for a number of days, I cannot figure out why this will not work. Any assistance would be greatly appreciated. I am thinking that there is probably a much easier way of accomplishing this that I am not aware of.
In the logcat I am seeing the following message:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String ca.vogl.r.tenpinbowlingcompanion.database.DatabaseHelper.leagueBowlerCount(java.lang.String)' on a null object reference.
As was pointed out below, the error seems to be happening in leagueBowlerCount(), which is listed above.
After making making the following addition to the onBindViewHolder : db = new DatabaseHelper (mainActivity). I am seeing values where I should be but they are not correct. See images below.
Test League 1 (there are three bowlers, one is hidden by the test ad)
Test League 2 (there is only 1 bowler)
Test League 3 (there are three bowlers, one is hidden by the test ad)
So basically you should be seeing a 3 for Test League 1, a 1 for Test League 2 and a 3 for Test League 3
So it now seems that the problem is with the leagueBowlercount function that I wrote. It is not getting the counts that are associated only to the individual league Id
I believe that your issue is that you are returning the id of the first selected bowler rather than the row count.
That is you, after checking the number of rows is greater than 0, move to the first row and then use count = cursor.getInt(0); which will be the value stored in the first column of the first row that has been extracted.
try using :-
public String leagueBowlerCount(String leagueId)
{
String rv = "0";
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(Bowler.TABLE_NAME,new String[]{"count(*)"},Bowler.COLUMN_LEAGUE_ID + "=?",new String[]{leagueId},null,null,null);
if (cursor.moveToFirst()) {
rv = String.valueOf(cursor.getLong(0));
}
cursor.close();
db.close();
return rv;
}
This uses the aggregate function count to extract the number of rows for the respective league.
Note the above code is in-principle code, it has not been tested or run and may therefore have some errors.
Alternatively you could use :-
public String leagueBowlerCount(String leagueId)
{
SQLiteDatabase db = this.getReadableDatabase();
String countQuery = "SELECT * FROM " + Bowler.TABLE_NAME + " WHERE " + Bowler.COLUMN_LEAGUE_ID + " = '" + leagueId + "'";
Cursor cursor = db.rawQuery(countQuery, null);
int count = cursor.getCount();
cursor.close();
db.close();
return String.valueOf(count);
}
In regard to your code :-
int count = 0;
if(null != cursor)
if(cursor.getCount() > 0){
cursor.moveToFirst();
count = cursor.getInt(0);
}
cursor.close();
Checking for a null Cursor is useless, as a Cursor returned from an SQLiteDatabase method, such as rawQuery, will never be null. Instead a valid, perhaps empty, Cursor will be returned.
Additionally checking if a Cursor has rows using the getCount method and then using moveToFirst is not needed as just using if (cursor.moveToFirst) {.....} is sufficient as if there are no rows the moveToFirst method will return false, as the move cannot be actioned.
I want to make a to-do list app, and I wanted to delete the item in the list by tapping the checkbox.
I tried to make a "deleteTask"(as you see in the code) method in the database class. Also, you can see the "populateListView"
method, it provides data from the database into listview, I use it to refresh after each time a task got deleted from the database.
public void deleteTask(String task) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_NAME, COL2 , new String[]{task});
}
public void populateListView() {
try {
mDataBaseHelper = new DataBaseHelper(MainActivity.this);
data = mDataBaseHelper.getData();
mArrayList = new ArrayList<>();
if (data.getCount() != 0) {
while (data.moveToNext()) {
mArrayList.add(data.getString(1));
ListAdapter listAdapter = new ArrayAdapter(MainActivity.this, R.layout.list_items, R.id.checkBox, mArrayList);
list = (ListView) findViewById(R.id.myListId);
list.setAdapter(listAdapter);
}
mDataBaseHelper.close();
} else {
toastMessage("the Database is empty");
}
}catch(Exception e){
Log.e(TAG, "populateListView: error"+e.getStackTrace() );
}
}
when the application gets started, I tapped the item that I want to delete, but I see that the items start to be deleted by order from above!
one by one each time I tapped any checkbox.
You want :-
public void deleteTask(String task) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_NAME, COL2 + "=?" , new String[]{task});
}
If you weren't trapping the error by using the try/catch using db.delete(TABLE_NAME, COL2 , new String[]{task}); you would get an exception along the lines of :-
java.lang.IllegalArgumentException: Too many bind arguments. 1 arguments were provided but the statement needs 0 arguments.
However
Assuming that the issue with deleting rows sequentially rather than according to the checked item(s), is likely due to the handling of the checked items. However, as the code for this is not provided it would only be guess work to know where in the code you are going wrong.
One thing is that you do not want to be creating a new listadapter instance every time you populate the ListView.
As a hint to handling a ListView, but deleting an item when it is long-clicked based upon the COL2 value, perhaps consider the following which has been based upon your code (but deletes according to long clicking an item) :-
public void populateLisView() {
mDataBaseHelper = new DataBaseHelper(this); //<<<<<<<<<< NOTE 1
list = (ListView) this.findViewById(R.id.myListId); //<<<<<<<<<< NOTE 1
data = mDataBaseHelper.getData(); //<<<<<<<<<< get the data to be listed
if (listadapter == null) { //<<<<<<<<<< Only need to instantiate one adapter when it has not bee instantiated
listadapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,android.R.id.text1,data); // for convenience using a stock layout
list.setAdapter(listadapter);
//<<<<<<<<<<< add the onItemLongClick listener
list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
mDataBaseHelper.deleteTaskByCol2(data.get(position)); //<<<<<<<<<< gets the value of the item according to it's position in the list
populateLisView(); //<<<<<<<<<< as the item has been deleted then refresh the Listview
return true; // flag the event as having been handled.
}
});
//<<<<<<<<<<< If the Adapter has been instantiated then refresh the ListView's data
} else {
listadapter.clear(); // Clear the data from the adapter
listadapter.addAll(data); // add the new changed data to the adapter
listadapter.notifyDataSetChanged(); // tell the adapter that the data has changed
}
}
NOTE 1
you would typically instantiate these variables once.
Check the comments
You may wish to edit your question to include how you are handling the check events.
The Full Working Example
DatabaseHelper.java
Note this may differ from yours a little
public class DataBaseHelper extends SQLiteOpenHelper {
public static final String DBNAME = "mydb";
public static final int DBVERSION = 1;
public static final String TABLE_NAME = "mytable";
public static final String COL1 = "col1";
public static final String COL2 = "col2";
SQLiteDatabase db;
private static final String CRT_MYTABLE_SQL = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME +
"(" +
COL1 + " TEXT, " +
COL2 + " TEXT" +
")";
public DataBaseHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
db = this.getWritableDatabase();
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CRT_MYTABLE_SQL);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public long addMytableRow(String col1, String col2) {
ContentValues cv = new ContentValues();
cv.put(COL1,col1);
cv.put(COL2,col2);
return db.insert(TABLE_NAME,null,cv);
}
public ArrayList<String> getData() {
ArrayList<String> rv = new ArrayList<>();
Cursor csr = db.query(TABLE_NAME,null,null,null,null,null,null);
while (csr.moveToNext()) {
rv.add(csr.getString(csr.getColumnIndex(COL2)));
}
csr.close();
return rv;
}
public void deleteTaskByCol2(String task) {
db.delete(TABLE_NAME,COL2 + "=?",new String[]{task});
}
}
MainActivity.java
i.e. an example activity that is based upon your code, but according to the above :-
public class MainActivity extends AppCompatActivity {
DataBaseHelper mDataBaseHelper;
ArrayList<String> data;
ListView list;
ArrayAdapter<String> listadapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addSomeTestData();
populateLisView();
}
private void example001() {
}
public void populateLisView() {
mDataBaseHelper = new DataBaseHelper(this);
list = (ListView) this.findViewById(R.id.myListId);
data = mDataBaseHelper.getData();
if (listadapter == null) {
listadapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,android.R.id.text1,data);
list.setAdapter(listadapter);
list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
//mDataBaseHelper.deleteTaskWrong(data.get(position)); // ooops
mDataBaseHelper.deleteTaskByCol2(data.get(position));
populateLisView();
return true;
}
});
} else {
listadapter.clear();
listadapter.addAll(data);
listadapter.notifyDataSetChanged();
}
}
private void addSomeTestData() {
if (mDataBaseHelper == null) {
mDataBaseHelper = new DataBaseHelper(this);
}
if (DatabaseUtils.queryNumEntries(mDataBaseHelper.getWritableDatabase(),DataBaseHelper.TABLE_NAME) > 0) return;
mDataBaseHelper.addMytableRow("Test1","Test1");
mDataBaseHelper.addMytableRow("Test2","Test2");
mDataBaseHelper.addMytableRow("Test3","Test3");
mDataBaseHelper.addMytableRow("Test4","Test4");
}
}
Note AddSomeTestData adds some data for testing/demonstration.
Result
When first run :-
After LongClicking Test 2
i.e. the long clicked item has been removed (from the list and the database) and the list refreshed.
Try to replace
db.delete(TABLE_NAME, COL2 , new String[]{task});
By
db.delete(TABLE_NAME, COL2 + " = ?" , new String[]{task});
I have RecyclerView which i am using for chat and all is working but reverse pagination like loading chat history from local SQLitedatabase is not working like Whatsapp Or Telegram App.
At first load i am loading user chat history by default with only 10 messages from Local SQLite Database. If i pull from top it loads next(older) 10 messages and so on.
I am using Firebase Realtime Database as our chat server which sync in realtime and when user send new message it fetch message and add into SQLite Database then loads at above oldest message Like in Image below
Main Class
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.chat_screen_main_fragment, container, false);
setRetainInstance(true);
// RECYCLER VIEW
recyclerView = v.findViewById(R.id.Chat_Screen_Message_List);
layoutManager = new LinearLayoutManager(getActivity());
layoutManager.scrollToPosition(message.size() - 1);
if (adapter == null) {
adapter = new Chat_Adapter(getActivity(), message);
}
layoutManager.setStackFromEnd(true);
layoutManager.setReverseLayout(true);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
chat_database=new Chat_Database(getActivity());
// Testing For Pagination
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL){
Log.d(TAG,"Hello I am scrolling screen ");
isScrolling = true;
}
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
currentVisible = layoutManager.getChildCount();
TotalItems = layoutManager.getItemCount();
scrolledOutItems = layoutManager.findFirstVisibleItemPosition();
int check = TotalItems - currentVisible+scrolledOutItems;
Log.d(TAG,"Current Visible = "+currentVisible+" Total = "+TotalItems+" Scrolled Out Items = "+scrolledOutItems+" Check = "+check);
if (isScrolling && TotalItems == currentVisible + scrolledOutItems ){
Log.d(TAG,"Fetch Data Now "+OFFSET);
if (chatCount > OFFSET){
Log.d(TAG,"Total item count is more than database = "+chatCount +" "+OFFSET);
new databaseAsync().execute();
isScrolling = false;
}
}
}
});
}
//THIS METHOD WILL FETCH ALL MESSAGES FROM FIREBASE DATABASE
private synchronized void append_chat_conversation(DataSnapshot dataSnapshot) {
Iterator iterator = dataSnapshot.getChildren().iterator();
while (iterator.hasNext()) {
// NOW GET ALL DATA FROM FIREBASE DATABASE AND SAVE IT INTO STRINGS THEN CHECK EACH BY ITS MESSAGE TYPE
Chat_Msg = (String) ((DataSnapshot) iterator.next()).getValue();
Chat_FROM = (String) ((DataSnapshot) iterator.next()).getValue();
Chat_TO = (String) ((DataSnapshot) iterator.next()).getValue();
Chat_Type= (String) ((DataSnapshot) iterator.next()).getValue();
if (Chat_Type.equals("Local_Image")) {
long id = chat_database.Insert_Chat(Session.getUserID(), "Image", Chat_Msg);
if (id==0){
return;
}
Chat_Wrapper image = new Chat_Wrapper(null, Chat_Msg, null, null, null, null, null, Chat_TimeStamp,id );
message.add(image);
adapter.notifyDataSetChanged();
recyclerView.post(new Runnable() {
#Override
public void run() {
recyclerView.smoothScrollToPosition(adapter.getItemCount());
}
});
} else if (Chat_Type.equals("Typed_Message")){
long id=chat_database.Insert_Chat(Session.getUserID(),"Text", Chat_Msg);
//Adding Chat Data Into Database
if (id==0){
return;
}
Chat_Wrapper chat_wrapper = new Chat_Wrapper(Chat_Msg, null, null, null, null, null, null, Chat_TimeStamp,id);
message.add(chat_wrapper);
adapter.notifyDataSetChanged();
recyclerView.post(new Runnable() {
#Override
public void run() {
recyclerView.smoothScrollToPosition(adapter.getItemCount());
}
});
}
}
//FETCHING DATA FROM LOCAL DATABASE
private class databaseAsync extends AsyncTask<Void,Void,Void> {
boolean checkDB_Exist,chatItemsCounts;
private Parcelable recyclerViewState;
#Override
protected void onPreExecute() {
super.onPreExecute();
Log.d(TAG,"Chat Database Function "+OFFSET);
if (OFFSET == 0){
message.clear();
}
recyclerViewState = recyclerView.getLayoutManager().onSaveInstanceState();
//chatCursor=chat_database.getUserChat(UserID_Intent);
chatCount = chat_database.getUserChatCount(UserID_Intent);
chatCursor=chat_database.getLimitUserChat(UserID_Intent,OFFSET);
chatCursor.moveToFirst();
}
#Override
protected Void doInBackground(Void... voids) {
if (checkDB_Exist && chatCursor.getCount()>0) {
chatCursor.moveToFirst();
do {
database_rowID = chatCursor.getInt(chatCursor.getColumnIndex("ID"));
database_userID = chatCursor.getString(chatCursor.getColumnIndex("USER_ID"));
database_ReceiverID = chatCursor.getString(chatCursor.getColumnIndex("RECEIVER_USER_ID"));
database_MessageType = chatCursor.getString(chatCursor.getColumnIndex("MESSAGE_TYPE"));
database_Message = chatCursor.getString(chatCursor.getColumnIndex("USER_MESSAGE"));
database_MsgFrom = chatCursor.getString(chatCursor.getColumnIndex("SENDER_NAME"));
database_MsgTo = chatCursor.getString(chatCursor.getColumnIndex("RECEIVER_NAME"));
database_TimeStamp = chatCursor.getString(chatCursor.getColumnIndex("TIME_STAMP"));
if (database_MessageType.equals("Image")) {
Log.d(TAG, "Message Type Is Image");
Log.d(TAG, "Row ID of Database " + database_rowID);
Chat_Wrapper image = new Chat_Wrapper(null, database_Message, null, null, null, null, null, database_TimeStamp, database_PhoneTo, UserImage_Intent, database_MsgFrom, null, null, database_rowID);
message.add(image);
} else if (database_MessageType.equals("Text")) {
Log.d(TAG, "Message Type Is Text");
Chat_Wrapper text = new Chat_Wrapper(database_Message, null, null, null, null, null, null, database_TimeStamp, database_PhoneTo, UserImage_Intent, database_MsgFrom, null, null, database_rowID);
message.add(text);
}
}
}
while (chatCursor.moveToNext()) ;
chatCursor.close();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
recyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);
adapter.notifyDataSetChanged();
OFFSET +=10;
}
}
Chat Adapter
public class Chat_Adapter extends RecyclerView.Adapter<Chat_Adapter.ViewHolder> {
Chat_Wrapper chat_wrapper;
//ARRAYLIST OF MESSAGES OBJECT CONTAINING ALL THE MESSAGES IN THE THREAD
List<Chat_Wrapper> arrayList_message;
public Chat_Adapter(Context context, List<Chat_Wrapper> message) {
this.context = context;
this.arrayList_message = message;
}
#Override
public Chat_Adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View Layout;
Log.d(TAG,"On Create View Holder Calling ");
if (viewType==1){
Log.d(TAG,"View Tyoe Is "+viewType);
Layout=LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_screen_message_item,parent,false);
// ImagePath=Session.getUserImage();
}
else {
Log.d(TAG,"View Type Is "+viewType);
Layout=LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_screen_message_item_other,parent,false);
// ImagePath=chat_wrapper.getImageView();
}
return new ViewHolder(Layout);
}
#Override
public void onBindViewHolder(final Chat_Adapter.ViewHolder holder, final int position) {
chat_wrapper=arrayList_message.get(position);
context=holder.itemView.getContext();
if (valueofImage){
// Showing Sent User Image in thumbnail
Glide.with(context).load(chat_wrapper.getImageSent()).apply(new RequestOptions()
.fitCenter()
.skipMemoryCache(true))
.thumbnail(0.1f)
.into(holder.Sent_Image);
}
}
else if (valueofMessage){
Log.d(TAG,"Value Of Message Running ImagePath "+ImagePath);
holder.Sent_Video.setVisibility(View.GONE);
holder.Sent_Image.setVisibility(View.GONE);
holder.TimeStampImage.setVisibility(View.GONE);
holder.TimeStampDoc.setVisibility(View.GONE);
holder.TimeStampVideo.setVisibility(View.GONE);
holder.Search_title.setVisibility(View.GONE);
holder.Search_link.setVisibility(View.GONE);
holder.Search_snippet.setVisibility(View.GONE);
holder.Google_Image.setVisibility(View.GONE);
holder.videoView.setVisibility(View.GONE);
holder.Doc_FileName.setVisibility(View.GONE);
holder.Doc_ImageView.setVisibility(View.GONE);
holder.Doc_FileSize.setVisibility(View.GONE);
holder.GeoFencing_Layout.setVisibility(View.GONE);
holder.GeoFencing_Image.setVisibility(View.GONE);
holder.GeoFencing_LatLng.setVisibility(View.GONE);
holder.Message.setVisibility(View.VISIBLE);
holder.TimeStamp.setVisibility(View.VISIBLE);
holder.User_Image.setVisibility(View.VISIBLE);
//CHECK SENDER IS SAME AS LOGGED IN USER
if ((Session.getUserFname()+" "+Session.getUserLname()).equals(chat_wrapper.getSender_UserName())){
ImagePath=Session.getUserImage();
Log.d(TAG,"Session.getUserImage() "+Session.getUserImage());
Log.d(TAG,"Value Of Message Running ImagePath "+ImagePath);
}
else {
holder.Message.setText(chat_wrapper.getMessage());
holder.TimeStamp.setText(chat_wrapper.getTimestamp());
}
#Override
public int getItemCount() {
Log.d(TAG,"GET ITEM COUNT--Array Message List Size "+arrayList_message.size());
return arrayList_message.size();
}
}
SQLite Query
//This method will get row by limit
public Cursor getLimitUserChat(String UserID,int nextChat){
database=this.getReadableDatabase();
cursor = database.rawQuery( "SELECT * FROM " + TABLE_NAME + " Where "+ RECEIVER_USERID +"="+ UserID+" ORDER BY ID DESC LIMIT 10 OFFSET "+nextChat+"",null
return cursor;
}
Using message.add(chat_wrapper); will put the added element to the end of the list so it will be shown at the end of the list while you are reversing the Recycler , use message.add(0,chat_wrapper); so it will be at the beginning of the array list.
I am trying to get a ListView to appear in a new activity. I can see the record ID in the logcat, and I can see that the proper ID is being selected in debug view, but when I go to the new activity the list array is empty.
This is what I am seeing in debug view:
In the logcat I see this:
2018-10-07 11:39:09.286 12624-12624/ca.rvogl.tpbcui D/SAVEDLEAGUEID_VAL: 1
2018-10-07 11:39:09.286 12624-12624/ca.rvogl.tpbcui D/LEAGUEID_VAL: android.support.v7.widget.AppCompatTextView{e67a170 G.ED..... ......I. 0,0-0,0 #7f080112 app:id/tvLeagueId}
2018-10-07 11:39:09.293 12624-12624/ca.rvogl.tpbcui D/GETALLBOWLERS-SQL: SQL used = >>>>SELECT * FROM bowlers WHERE league_id = '1' ORDER BY timestamp DESC<<<<
2018-10-07 11:39:09.298 12624-12624/ca.rvogl.tpbcui D/GETALLBOWLERS-CNT: Number of rows retrieved = 0
2018-10-07 11:39:09.299 12624-12624/ca.rvogl.tpbcui D/GETALLBOWLERS-CNT: Number of elements in bowlerslist = 0
As you can see from the logcat the savedLeagueId is being passed to the SQLite Query that is suppose to be getting the list of Bowlers for the listview. However the number of elements in the bowlerslist is 0.
I have gone through the code over and over again but I am unable to isolate where the issue is.
LeagueAdapter.java
public class LeagueAdapter extends RecyclerView.Adapter<LeagueAdapter.MyViewHolder> {
private Context context;
private List<League> leaguesList;
public void notifyDatasetChanged(List<League> newleagueslist) {
leaguesList.clear();
leaguesList.addAll(newleagueslist);
super.notifyDataSetChanged();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView name;
public TextView basescore;
public TextView basescorepercentage;
public TextView id;
public TextView wins;
public TextView losses;
public TextView timestamp;
public TextView buttonViewOption;
public MyViewHolder(View view) {
super(view);
id = view.findViewById( R.id.tvLeagueId);
name = view.findViewById(R.id.tvSeriesName );
basescore = view.findViewById(R.id.tvBaseScore );
basescorepercentage = view.findViewById(R.id.tvBaseScorePercentage );
wins = view.findViewById(R.id.tvLeagueWins );
losses = view.findViewById(R.id.tvLeagueLosses );
timestamp = view.findViewById(R.id.timestamp);
buttonViewOption = (TextView) view.findViewById(R.id.buttonViewOptions);
}
}
public LeagueAdapter(Context context, List<League> leaguesList) {
this.context = context;
this.leaguesList = leaguesList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.listview_league, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
League league = leaguesList.get(position);
int id = league.getId();
Log.d("id", String.valueOf(id));
int leagueId = id;
Log.d("leagueId", String.valueOf(leagueId));
holder.id.setText(String.valueOf(leagueId));
holder.name.setText(league.getName());
holder.basescore.setText(league.getBaseScore());
holder.basescorepercentage.setText(league.getBaseScorePercentage());
holder.wins.setText(league.getWins());
holder.losses.setText(league.getLosses());
/*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:
Log.d("leagueId", String.valueOf(position));
int leagueId = league.getId();
String savedLeagueId = String.valueOf(id);
Intent myIntent = new Intent(context, LeagueProfileViewActivity.class);
myIntent.putExtra("leagueId", leagueId);
context.startActivity(myIntent);
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) {
//String leagueId = String.valueOf(leaguesList.get(position).getId());
int leagueId = league.getId();
String savedLeagueId = String.valueOf(id);
Log.d("leagueId", String.valueOf(position));
Intent myIntent = new Intent(context, BowlerActivity.class);
myIntent.putExtra("leagueId", savedLeagueId);
context.startActivity(myIntent);
}
});
}
#Override
public int getItemCount() {
return leaguesList.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 "";
}
}
I am moving to the BowlerActivity using holder.name, where I am passing the League ID using an intent.
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().getStringExtra("leagueId"));
leagueId = findViewById(R.id.tvLeagueId);
Log.d("SAVEDLEAGUEID_VAL", String.valueOf(savedLeagueId));
Log.d("LEAGUEID_VAL", String.valueOf(leagueId));
/*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);
boolean shouldUpdate = false;
int bowlerId = -1;
String leagueId = String.valueOf(savedLeagueId);
Intent intent = new Intent(getApplicationContext(), BowlerProfileEditActivity.class);
intent.putExtra("shouldUpdate", shouldUpdate);
intent.putExtra("leagueId", leagueId);
intent.putExtra("bowlerId", bowlerId);
startActivity(intent);
finish();
overridePendingTransition(0, 0);
}
});
mAdapter = new BowlerAdapter(this, bowlersList);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
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(savedLeagueId, bowlerName, bowlerAverage);
//Get The Newly Inserted Bowler From The Database
Bowler n = db.getBowler(savedLeagueId);
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();
}
//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);
}
}
Bowler Methods in DatabaseHelper.java
public long insertBowler(String leagueId, String bowlerName, String bowlerAverage) {
String bowlerHandicap ="0";
//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);
values.put(Bowler.COLUMN_BOWLER_AVERAGE, bowlerAverage);
values.put(Bowler.COLUMN_BOWLER_HANDICAP, bowlerHandicap);
//Insert Row
//long id = db.insert(Bowler.TABLE_NAME, null, values);
long id = db.insertOrThrow( Bowler.TABLE_NAME, null, values );
Log.d("INSERTBOWLER","Number of bowlers in db = " + String.valueOf( DatabaseUtils.queryNumEntries(db,Bowler.TABLE_NAME)));
//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_BOWLER_AVERAGE, Bowler.COLUMN_BOWLER_HANDICAP, Bowler.COLUMN_TIMESTAMP},
Bowler.COLUMN_LEAGUE_ID + "=?",
new String[]{String.valueOf(leagueId)}, null, null, null, null);
Bowler bowler = null;
if (cursor.moveToFirst()) {
//Prepare Bowler Object
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_BOWLER_AVERAGE)),
cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_BOWLER_HANDICAP)),
cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_TIMESTAMP)));
//Close Database Connection
cursor.close();
return bowler;
} else {
return bowler;
}
}
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.setAverage(cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_BOWLER_AVERAGE)));
bowler.setHandicap(cursor.getString(cursor.getColumnIndex(Bowler.COLUMN_BOWLER_HANDICAP)));
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());
values.put(Bowler.COLUMN_BOWLER_AVERAGE, bowler.getAverage());
//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();
}
I am hoping that someone will be able to point out what I am doing incorrectly in order to fix this issue.
If any additional information is need please let me know and I will post it.
I have figured out why all my new bowler entries have an id of 2. In my edit Bowler Profile Activity I have the following : leagueId = String.valueOf(getIntent().getIntExtra("leagueId",2)); The default value is 2 and because I was not grabbing the information being passed to the new Activity in the proper manner the app was always using 2 as the BowlerId.
I changed the code that was capturing the information from the intent to the following:
Intent intent = getIntent();
leagueId = intent.getStringExtra("leagueId");
With this change I was able to capture all the bowlers that belong to a particular league. I only realized that I was passing the information incorrectly after reading through the following post:
Pass a String from one Activity to another Activity in Android
I am facing a problem with Android app.So. I have 3 activities that are opening one after another with OnItemClickListener. From first to second activity I have no trouble since I just have to load ArrayList in listview in the second activity.The third activity is opening when I click an item from the listview in second activity and in a third activity I want to open data from my database for the clicked item.
Here is some code:
1.The second activity:
DatabaseHelper myDB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.viewlistcontents_layout);
ListView listView = (ListView) findViewById(R.id.listView);
myDB = new DatabaseHelper(this);
ArrayList<String> theList = new ArrayList<>();
Cursor data = myDB.getListContents();
if(data.getCount() == 0){
Toast.makeText(this, "There are no contents in this list!",Toast.LENGTH_LONG).show();
}else{
while(data.moveToNext()){
theList.add(data.getString(1));
ListAdapter listAdapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,theList);
listView.setAdapter(listAdapter);
}
}
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(ViewListContents.this, ElevatorInfo.class);
startActivity(intent);
}
});
}
2.Third activity where I want to get the opened item id from a database and load the third column from the database but have no idea how to do it and that is my actual question.Also, im doing the same thing as in second activity just to try to load the info from the third column in a listview but its also not working.
DatabaseHelper myDB;
#Override
ListView listView = (ListView) findViewById(R.id.listView);
myDB = new DatabaseHelper(this);
ArrayList<String> theList = new ArrayList<>();
Cursor data = myDB.getListContents();
if (data.getCount() == 0) {
Toast.makeText(this, "There are no contents in this list!", Toast.LENGTH_LONG).show();
} else {
while (data.moveToNext()) {
theList.add(data.getString(2));
ListAdapter listAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, theList);
listView.setAdapter(listAdapter);
}
}
}
public void AddData(String newEntry) {
boolean insertData = myDB.addData2(newEntry);
if(insertData == true){
Toast.makeText(this, "Data Successfully Inserted!", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(this, "Something went wrong :(.", Toast.LENGTH_LONG).show();
}
}
}
3.My DatabaseHelper class.
#Override
public void onCreate(SQLiteDatabase db) {
String createTable = "CREATE TABLE " + MyDatabase.ElevatorEntry.TABLE_NAME + " ( " + MyDatabase.ElevatorEntry.COL1 + "INTEGER PRIMARY KEY AUTOINCREMENT, " +
MyDatabase.ElevatorEntry.COL2 + "TEXT" + MyDatabase.ElevatorEntry.DATE + " TEXT " + " )";
db.execSQL(createTable);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP IF TABLE EXISTS " + MyDatabase.ElevatorEntry.TABLE_NAME);
onCreate(db);
}
public boolean addData(String item1) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(MyDatabase.ElevatorEntry.COL2, item1);
long result = db.insert(MyDatabase.ElevatorEntry.TABLE_NAME, null, contentValues);
if (result == -1) {
return false;
} else {
return true;
}
}
public boolean addData2(String item2) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(MyDatabase.ElevatorEntry.DATE, item2);
public Cursor getListContents(){
SQLiteDatabase db = this.getWritableDatabase();
Cursor data = db.rawQuery("SELECT * FROM " + MyDatabase.ElevatorEntry.TABLE_NAME, null );
return data;
}
}
you have wrote a lot of code in the question, stay focused on what you want to ask about
side note: why this
ListAdapter listAdapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,theList);
listView.setAdapter(listAdapter);
is in the while loop? this should be called once, when the loop ends and all the items have been added to the list theList
while(data.moveToNext()){
theList.add(data.getString(1));
}//while loop
ListAdapter listAdapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,theList);
listView.setAdapter(listAdapter);
Now, for your question, at onItemClick() use position to get the item from theList then do whatever you want with it:
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String selected = theList.get(position);
Intent intent = new Intent(ViewListContents.this, ElevatorInfo.class);
intent.putExtra("SELECTED_ITEM",selected);
startActivity(intent);
}
now you can add selected as an extra in the intent and start the next activity.
EDIT:
For how to read the value from the 2nd activity. check this answer
you need to use getIntent().getStringExtra("SELECTED_ITEM");.