dynamically update RecyclerView on SqLite database dataset change - android

I have a fairly simple implementation of a high score leader board here that saves the name provided by the user alongside his or her score.
Unfortunately, upon returning to the high score activity the RecyclerView will only show the score that had previously been populated, not the new one that was just entered. I am using notifyDatasetChanged() method in an async task. Still no success. Any pointers are much appreciated.
The high score activity:
public class HighscoreActivity extends AppCompatActivity implements View.OnClickListener{
SQLiteDatabase db;
ArrayList<String> nameList;
ArrayList<String> scoreList;
RecyclerView recyclerView;
ScoreRecViewAdapter scoreRecViewAdapter;
Button buttonStart;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_highscore);
buttonStart = findViewById(R.id.buttonStart);
buttonStart.setOnClickListener(this);
// create lists and table
nameList = new ArrayList<>();
scoreList = new ArrayList<>();
db = this.openOrCreateDatabase("Scores", MODE_PRIVATE, null);
db.execSQL("CREATE TABLE IF NOT EXISTS scores(name VARCHAR, score VARCHAR)");
//Cursor c = db.rawQuery("SELECT * FROM scores", null);
Cursor c = db.rawQuery("SELECT * FROM scores ORDER BY score DESC", null);
// Fill list
int nameIndex = c.getColumnIndex("name");
int scoreIndex = c.getColumnIndex("score");
while ( c.moveToNext() ){
nameList.add(c.getString(nameIndex));
scoreList.add(c.getString(scoreIndex));
}
// put data in rec view
recyclerView = findViewById(R.id.recView);
scoreRecViewAdapter = new ScoreRecViewAdapter(this, nameList, scoreList);
recyclerView.setAdapter(scoreRecViewAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// enter new user data
Intent getter = getIntent();
String nameExtra = getter.getStringExtra("name");
String scoreExtra = getter.getStringExtra("score");
if( nameExtra != null && scoreExtra != null) {
// perform async task
new InsertIntoDatabase().execute(nameExtra, scoreExtra);
}
}
#Override
public void onClick(View view) {
if (view.getId() == R.id.buttonStart) {
Intent actorQuizz = new Intent(this, MainActivity.class);
startActivity(actorQuizz);
}
}
public class InsertIntoDatabase extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... strings) {
db.execSQL("INSERT INTO scores (name, score) VALUES ('" + strings[0] + "', '" + strings[1] +"')");
Log.i("score saved", "success");
return "success";
}
#Override
protected void onPostExecute(String s) {
//nameList.clear();
//scoreList.clear();
Cursor c = db.rawQuery("SELECT * FROM scores", null);
// Fill list
int nameIndex = c.getColumnIndex("name");
int scoreIndex = c.getColumnIndex("score");
while ( c.moveToNext() ){
nameList.add(c.getString(nameIndex));
scoreList.add(c.getString(scoreIndex));
}
scoreRecViewAdapter.notifyDataSetChanged();
}
}
}
and the recyclerview adapter:
public class ScoreRecViewAdapter extends RecyclerView.Adapter {
Context mContext;
ArrayList<String> nameList;
ArrayList<String> scoreList;
public ScoreRecViewAdapter (Context context, ArrayList<String> nameList, ArrayList<String> scoreList) {
this.mContext = context;
this.nameList = nameList;
this.scoreList = scoreList;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(mContext).inflate(R.layout.rec_menu,parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.nameView.setText(nameList.get(position));
holder.scoreView.setText(scoreList.get(position));
}
#Override
public int getItemCount() {
return nameList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView nameView;
TextView scoreView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
nameView = itemView.findViewById(R.id.textViewName);
scoreView = itemView.findViewById(R.id.textViewScore);
}
}
}

Related

The first row of my SQLite Database is not getting fetched and displayed in my RecyclerView

This is my dbmanager class:
public class dbmanager extends SQLiteOpenHelper {
String sgpa_table="create table Sgpa (sname text, semester text, sgpa int,percent int, schemes int, primary key(sname,semester,schemes))";
public dbmanager(#Nullable Context context) {
super(context, "Student", null, 1);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(sgpa_table);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public Cursor fetch_data1() {
SQLiteDatabase db = this.getWritableDatabase();
String query = "Select*FROM Sgpa" ;
Cursor cursor = db.rawQuery(query,null);
if (cursor != null) {
cursor.moveToFirst();
}
return cursor;
}
}
This is my Adapter class:
public class adapter_sgpa extends RecyclerView.Adapter<adapter_sgpa.Viewholder> {
ArrayList<POJO> sgpaArrayList;
public adapter_sgpa(ArrayList<POJO> sgpaArrayList) {
this.sgpaArrayList = sgpaArrayList;
}
#NonNull
#Override
public adapter_sgpa.Viewholder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View listitem = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_sgpa, parent, false);
return new Viewholder(listitem);
}
#Override
public void onBindViewHolder(#NonNull adapter_sgpa.Viewholder holder, int position) {
POJO sgpa= sgpaArrayList.get(position);
holder.sname.setText(sgpa.getSname());
holder.semester.setText(sgpa.getSemester());
holder.sgpa.setText(Integer.toString(sgpa.getSgpa()));
holder.percent.setText(Integer.toString(sgpa.getPercent()));
holder.schemes.setText(Integer.toString(sgpa.getSchemes()));
}
#Override
public int getItemCount() {
return sgpaArrayList.size();
}
public class Viewholder extends RecyclerView.ViewHolder {
TextView sname, semester, sgpa, percent, schemes;
//ImageButton btndelete1;
public Viewholder(#NonNull View itemView) {
super(itemView);
sname = (TextView) itemView.findViewById(R.id.textView2);
semester = (TextView) itemView.findViewById(R.id.semester);
sgpa = (TextView) itemView.findViewById(R.id.textV);
percent = (TextView) itemView.findViewById(R.id.textVw);
schemes = (TextView) itemView.findViewById(R.id.scheme1);
// btndelete1 = (ImageButton) itemView.findViewById(R.id.btndelete1);
}
}
}
This is sgpa_frag which is like my main class:
public class sgpa_frag extends Fragment {
//View view;
RecyclerView recyclerview;
adapter_sgpa ac;
TextView else2;
ArrayList<POJO> sgpaArrayList;
public sgpa_frag() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_sgpa_frag, container, false);
recyclerview= (RecyclerView) view.findViewById(R.id.rc1);
else2=(TextView)view.findViewById(R.id.else2);
sgpaArrayList= new ArrayList<>();
ac= new adapter_sgpa(sgpaArrayList);
recyclerview.setLayoutManager(new LinearLayoutManager(getContext(),RecyclerView.VERTICAL,true));
recyclerview.setAdapter(ac);
Fetchdata1();
return view;
}
private void Fetchdata1()
{
dbmanager db= new dbmanager(getContext());
Cursor cursor= db.fetch_data1();
if (cursor!= null){
cursor.moveToFirst();
while (cursor.moveToNext()){
//ModelDetail cd= new ModelDetail(cursor.getString(1),cursor.getString(2),cursor.getString(3),cursor.getString(4));
POJO pj= new POJO();
pj.setSname(cursor.getString(0));
pj.setSemester(cursor.getString(1));
pj.setSgpa(cursor.getInt(2));
pj.setPercent(cursor.getInt(3));
pj.setSchemes(cursor.getInt(4));
sgpaArrayList.add(pj);
}
ac= new adapter_sgpa(sgpaArrayList);
recyclerview.setAdapter(ac);
}
else{
else2.setVisibility(View.VISIBLE);
}
}
}
The first row of my SQLite Database is not getting fetched and displayed in my RecyclerView.
The other rows are getting displayed but only the first one is not getting displayed.
Can someone point me out where I am going wrong?
From this part of your code in Fetchdata1():
if (cursor!= null){
cursor.moveToFirst();
while (cursor.moveToNext()){
..................................
remove cursor.moveToFirst();
because cursor.moveToNext() will advance the cursor's index to the 2nd row and the 1st row will not be added to the list.
Also inside fetch_data1() inside dbmanager remove this:
if (cursor != null) {
cursor.moveToFirst();
}

Delete ListiView and SQLite row in Android

I'm developing an application in Android Studio using this library: com.daimajia.swipelayout:library:1.2.0#aar. My app user a SQLite database with the following classes:
BDSQLiteHelper.java
public class BDSQLiteHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "ExtraOficial";
private static final String TABELA_VAZAMENTOS = "VazamentosToSQL";
private static final String vazID = "VazID";
private static final String nomeServico = "nomeServico";
private static final String[] VAZ_COLUNAS = {vazID, nomeServico};
public BDSQLiteHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_VAZAMENTOTABLE = "CREATE TABLE VazamentosToSQL ("+
"vazID INTEGER PRIMARY KEY AUTOINCREMENT,"+
"nomeServico)";
db.execSQL(CREATE_VAZAMENTOTABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
db.execSQL("DROP TABLE IF EXISTS VazamentosToSQL");
this.onCreate(db);
}
public void addVazamentos(VazamentosToSQL VazamentosToSQL) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(nomeServico, VazamentosToSQL.getNomeServico());
db.insert(TABELA_VAZAMENTOS, null, values);
db.close();
}
public VazamentosToSQL getVazamentos (int vazID) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABELA_VAZAMENTOS,
VAZ_COLUNAS,
" vazID = ?",
new String[] {String.valueOf(vazID)},
null,
null,
null,
null);
if (cursor == null) {
return null;
} else {
cursor.moveToFirst();
VazamentosToSQL VazamentosToSQL = cursorTovazamentos(cursor);
return VazamentosToSQL;
}
}
private VazamentosToSQL cursorTovazamentos(Cursor cursor) {
VazamentosToSQL VazamentosToSQL = new VazamentosToSQL();
VazamentosToSQL.setVazID(Integer.parseInt(cursor.getString(0)));
VazamentosToSQL.setNomeServico(cursor.getString(1));
return VazamentosToSQL;
}
public ArrayList<VazamentosToSQL> getAllVazamentos() {
ArrayList<VazamentosToSQL> listaVazamentos = new ArrayList<VazamentosToSQL>();
String query = "SELECT * FROM " + TABELA_VAZAMENTOS + " ORDER BY "+ vazID + " DESC";
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(query, null);
if (cursor.moveToFirst()) {
do {
VazamentosToSQL VazamentosToSQL = cursorTovazamentos(cursor);
listaVazamentos.add(VazamentosToSQL);
} while (cursor.moveToNext());
}
return listaVazamentos;
}
[...]
public int deleteVazamentos(VazamentosToSQL VazamentosToSQL) {
SQLiteDatabase db = this.getWritableDatabase();
int i = db.delete(TABELA_VAZAMENTOS,
vazID+" =?",
new String[] { String.valueOf(VazamentosToSQL.getVazID())});
db.close();
return i;
}
VazamentosToSQL.java
public class VazamentosToSQL {
private int vazID;
private String nomeServico;
public int getVazID() { return vazID; }
public void setVazID(int vazID) {
this.vazID = vazID;
}
public String getNomeServico() { return nomeServico; }
public void setNomeServico(String nomeServico) { this.nomeServico = nomeServico; }
}
ListViewActivity.java:
[...]
//variables
private BDSQLiteHelper bd;
ArrayList<VazamentosToSQL> listaVazamentos;
SwipeLayout swipeLayout;
private final static String TAG = ListViewActivity.class.getSimpleName();
vazamentosAdapter adapter;
ListView lista;
[...]
#Override
protected void onCreate(Bundle savedInstanceState)
{super.onCreate(savedInstanceState);
[...]
bd = new BDSQLiteHelper(this);
lista = (ListView) findViewById(R.id.lvdenuncias);
listaVazamentos = bd.getAllVazamentos();
setListViewHeader();
setListViewAdapter();
lista.setOnItemClickListener(new AdapterView.OnItemClickListener() { //aqui é o vazamentosAdapter
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent intent = new Intent(ExibeVazamentosActivity.this, DetalhesVazamentosActivity.class);
intent.putExtra("vazID", listaVazamentos.get(position).getVazID());
startActivity(intent);
}
});
#Override
protected void onStart() {
super.onStart();
updateAdapter(); //Refresh ListView items
}
private void setListViewHeader() {
LayoutInflater inflater = getLayoutInflater();
View header = inflater.inflate(R.layout.header_listview, lista, false);
totalClassmates = (TextView) header.findViewById(R.id.total);
swipeLayout = (SwipeLayout)header.findViewById(R.id.swipe_layout);
setSwipeViewFeatures();
//UNNECESSARY for me: lista.addHeaderView(header);
}
private void setSwipeViewFeatures() {
swipeLayout.setShowMode(SwipeLayout.ShowMode.PullOut);
//add drag edge.(If the BottomView has 'layout_gravity' attribute, this line is unnecessary)
swipeLayout.addDrag(SwipeLayout.DragEdge.Left, findViewById(R.id.bottom_wrapper));
swipeLayout.addSwipeListener(new SwipeLayout.SwipeListener() {
#Override
public void onClose(SwipeLayout layout) {
Log.i(TAG, "onClose");
}
#Override
public void onUpdate(SwipeLayout layout, int leftOffset, int topOffset) {
Log.i(TAG, "on swiping");
}
#Override
public void onStartOpen(SwipeLayout layout) {
Log.i(TAG, "on start open");
}
#Override
public void onOpen(SwipeLayout layout) {
Log.i(TAG, "the BottomView totally show");
}
#Override
public void onStartClose(SwipeLayout layout) {
Log.i(TAG, "the BottomView totally close");
}
#Override
public void onHandRelease(SwipeLayout layout, float xvel, float yvel) {
//when user's hand released.
}
});
}
private void setListViewAdapter() {
adapter = new vazamentosAdapter(this, listaVazamentos);
lista.setAdapter(adapter);
}
public void updateAdapter() {
listaVazamentos.clear();
listaVazamentos.addAll(bd.getAllVazamentos());
adapter.notifyDataSetChanged(); //update adapter
lista.invalidateViews();
lista.refreshDrawableState();
}
}
vazamentosAdapter.java:
public class vazamentosAdapter extends ArrayAdapter<VazamentosToSQL> {
private final Context context;
private final ArrayList<VazamentosToSQL> elementos;
File imgFile;
private Bitmap bitmap;
private ExifInterface exifObject;
private ExibeVazamentosActivity activity;
int vazID;
private SQLiteDatabase bd;
public vazamentosAdapter(Context context, ArrayList<VazamentosToSQL> elementos) {
super(context, R.layout.linha, elementos);
this.context = context;
this.elementos = elementos;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
// inflate UI from XML file
convertView = inflater.inflate(R.layout.linha, parent, false);
// get all UI view
holder = new ViewHolder(convertView);
// set tag for holder
convertView.setTag(holder);
}else {
// if holder created, get tag from view
holder = (ViewHolder) convertView.getTag();
}
[...]
editText.setText(elementos.get(position).getVaznomeServico());
holder.btnEdit.setOnClickListener(onEditListener(position, holder));
holder.btnDelete.setOnClickListener(onDeleteListener(position, holder));
return convertView;
}
private View.OnClickListener onDeleteListener(final int position, final ViewHolder holder) {
return new View.OnClickListener() {
#Override
public void onClick(View v) {
/**--------------Tried it, not working =( ---------------*/
elementos.get(position).getVazID();
//listaVazamentos.remove(position);
//activity.listaVazamentos.remove(position);
//bd = context.openOrCreateDatabase("DesoExtraOficial", Activity.MODE_PRIVATE, null);
//bd.execSQL("DELETE from VazamentosToSQL where vazID = '" + elementos.get(position).getVazID() + "'");
//bd.close();
//elementos.remove(position);
Toast.makeText(context, "ID: "+elementos.get(position).getVazID(),Toast.LENGTH_LONG).show();
bd.deleteVazamentos(VazamentosToSQL);
holder.swipeLayout.close();
// activity.updateAdapter(); //Executa o método "updateAdapter()" na Activity "ExibeVazamentos"
/**--------------Tried it, not working =( ---------------*/
}
};
}
private class ViewHolder {
private TextView name;
private View btnDelete;
private View btnEdit;
private SwipeLayout swipeLayout;
private ListView listv;
public ViewHolder(View v) {
swipeLayout = (SwipeLayout)v.findViewById(R.id.swipe_layout);
btnDelete = v.findViewById(R.id.delete);
btnEdit = v.findViewById(R.id.edit_query);
listv = (ListView) v.findViewById(R.id.lvdenuncias);
swipeLayout.setShowMode(SwipeLayout.ShowMode.PullOut);
}
}
The mentioned library is working great. But i'm trying to delete database row when user click in a button according to the listview selected line. With this code: elementos.get(position).getVazID() I get the database index. But I can't delete from database. Someone can help me with the code to delete row from database and line from listview?
Try changing this:
public int deleteVazamentos(VazamentosToSQL VazamentosToSQL) {
SQLiteDatabase db = this.getWritableDatabase();
int i = db.delete(TABELA_VAZAMENTOS, vazID+" =?", new String[] { String.valueOf(VazamentosToSQL.getVazID())});
db.close();
return i;
}
To this:
public void deleteVazamentos(int vazID) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABELA_VAZAMENTOS, "vazID=" + vazID, null);
}
Then if you want to delete a row, you can call:
(Inside onDeleteListener)
bd.deleteVazamentos(elementos.get(position).getVazID());

Properly delete an sqlite entry from a recyclerView click

my app stores name and result in SQLite database and displays that in RecycleViewer. Previously I use a listView where on LongClick I could delete an item like here LuckyNumbersApk/commit/4cec554359662d557626935046b8de68fb1b5c60
now I have switched to recyclerView I can't handle it properly. When I delete it, it disapears but when I reload the fragment the deleted entry reappears again. I assume it because the item is deleted only from the list in the adapter but how can I delete it from the list that is in the fragment that actually calls the recylerViewer?
This is my Adapter:
public class DatabaseAdapter extends RecyclerView.Adapter {
List dataModelArrayList;
Context context;
public DatabaseAdapter(List<DataModel> dataModelArrayList, Context context) {
this.dataModelArrayList = dataModelArrayList;
this.context = context;
}
class Myholder extends RecyclerView.ViewHolder implements CardView.OnLongClickListener {
TextView name, result;
public Myholder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.card_name);
result = (TextView) itemView.findViewById(R.id.card_result);
CardView cardView = (CardView) itemView.findViewById(R.id.card_view);
cardView.setOnLongClickListener(this);
}
#Override
public boolean onLongClick(View v) {
new AlertDialog.Builder(context)
.setIcon(R.drawable.ic_warning_black_24dp)
.setTitle("Delete result")
.setMessage("Are you sure you want delete this result?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
/* This is where deletions should be handled */
int id = getAdapterPosition();
DataBHelper database = new DataBHelper(context);
database.deleteEntry(id);
dataModelArrayList.remove(id);
notifyItemRemoved(id);
notifyDataSetChanged();
database.close();
}
})
.setNegativeButton("No", null)
.show();
return true;
}
}
#Override
public Myholder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row, null);
return new Myholder(view);
}
#Override
public void onBindViewHolder(Myholder holder, int position) {
DataModel dataModel = dataModelArrayList.get(position);
holder.name.setText(dataModel.getName());
holder.result.setText(dataModel.getResult());
}
#Override
public int getItemCount() {
return dataModelArrayList.size();
}}
This is DataBHelper:
public class DataBHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 2;
public static final String DATABASE_NAME = "results_database";
public static final String RESULTS_TABLE_NAME = "results_table";
public static final String RESULTS_COLUMN_ID = "_id";
public static final String RESULTS_COLUMN_NAME = "name";
public static final String RESULTS_COLUMN_RESULT = "result";
public DataBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL("CREATE TABLE " + RESULTS_TABLE_NAME + " (" +
RESULTS_COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
RESULTS_COLUMN_NAME + " TEXT, " +
RESULTS_COLUMN_RESULT + " TEXT" + ")");
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + RESULTS_TABLE_NAME);
onCreate(sqLiteDatabase);
}
public void saveToDB(String fname, String lname, String result) {
SQLiteDatabase database = getWritableDatabase();
ContentValues values = new ContentValues();
String name = fname + " " + lname;
values.put(DataBHelper.RESULTS_COLUMN_NAME, name);
values.put(DataBHelper.RESULTS_COLUMN_RESULT, result);
database.insert(DataBHelper.RESULTS_TABLE_NAME, null, values);
database.close();
}
public List<DataModel> readDB(){
List<DataModel> data=new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("select * from "+RESULTS_TABLE_NAME+" ;",null);
StringBuffer stringBuffer = new StringBuffer();
DataModel dataModel = null;
while (cursor.moveToNext()) {
dataModel= new DataModel();
String name = cursor.getString(cursor.getColumnIndexOrThrow("name"));
String result = cursor.getString(cursor.getColumnIndexOrThrow("result"));
dataModel.setName(name);
dataModel.setResult(result);
stringBuffer.append(dataModel);
data.add(dataModel);
}
return data;
}
public void clearDatabase() {
SQLiteDatabase sqLiteDatabase = getWritableDatabase();
String clearDBQuery = "DELETE FROM "+RESULTS_TABLE_NAME;
sqLiteDatabase.execSQL(clearDBQuery);
}
public void deleteEntry(long row) {
SQLiteDatabase sqLiteDatabase = getWritableDatabase();
sqLiteDatabase.delete(RESULTS_TABLE_NAME, RESULTS_COLUMN_ID + "=" + row, null);
}}
And this is the fragment which loads recyclerViewer
public class ResultsFragment extends Fragment {
DataBHelper database;
RecyclerView recyclerView;
DatabaseAdapter recycler;
public List<DataModel> datamodel;
#Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_results,
container, false);
datamodel =new ArrayList<DataModel>();
recyclerView = (RecyclerView) view.findViewById(R.id.app_recycle_view);
database = new DataBHelper(getActivity());
datamodel = database.readDB();
recycler = new DatabaseAdapter(datamodel, getActivity());
RecyclerView.LayoutManager reLayoutManager =new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(reLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(recycler);
ImageView imageView = (ImageView) view.findViewById(R.id.imageView);
if (datamodel.isEmpty()) {
recyclerView.setVisibility(View.GONE);
imageView.setVisibility(View.VISIBLE);
}
else {
recyclerView.setVisibility(View.VISIBLE);
imageView.setVisibility(View.GONE);
}
return view;
}}
In onCreateViwHolder:
#Override
public void onBindViewHolder(Myholder holder, int position) {
DataModel dataModel = dataModelArrayList.get(position);
holder.name.setText(dataModel.getName());
holder.result.setText(dataModel.getResult());
holder.id = dataModel.getId();
}
Add long id; into the ViewHolder, so your onClick you can delete the int id = getAdapterPosition(); and the id will be the id from the model.
To remove still use the adapter position:
dataModelArrayList.remove(getAdapterPosition());
notifyItemRemoved(getAdapterPosition());

How to create a LeaderBoard in Android Studio?

Main Activity code
I want to insert this
public void method() {
name = LoginActivity.name;
score = GameView.valueCurrent;
ContentValues values = new ContentValues();
values.put("name", name);
values.put("score", score);
}
And dont " myDB.execSQL("INSERT INTO scores (name, score) VALUES ('Marie', '4');");"
public class MainActivity extends AppCompatActivity {
private List<Items> itemsList = new ArrayList<Items>();
private ListView listView;
private CustomListAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SQLiteDatabase myDB = null;
try {
//Create a Database if doesnt exist otherwise Open It
myDB = this.openOrCreateDatabase("leaderboard", MODE_PRIVATE, null);
//Create table in database if it doesnt exist allready
myDB.execSQL("CREATE TABLE IF NOT EXISTS scores (name TEXT, score TEXT);");
//Select all rows from the table
Cursor cursor = myDB.rawQuery("SELECT * FROM scores", null);
//If there are no rows (data) then insert some in the table
if (cursor != null) {
if (cursor.getCount() == 0) {
/*** In this case i want to put the values of the Users that are playing my app
myDB.execSQL("INSERT INTO scores (name, score) VALUES ('Andy', '7');");
myDB.execSQL("INSERT INTO scores (name, score) VALUES ('Marie', '4');");
myDB.execSQL("INSERT INTO scores (name, score) VALUES ('George', '1');");
**//
}
}
} catch (Exception e) {
} finally {
//Initialize and create a new adapter with layout named list found in activity_main layout
listView = (ListView) findViewById(R.id.list);
adapter = new CustomListAdapter(this, itemsList);
listView.setAdapter(adapter);
Cursor cursor = myDB.rawQuery("SELECT * FROM scores", null);
if (cursor.moveToFirst()) {
//read all rows from the database and add to the Items array
while (!cursor.isAfterLast()) {
Items items = new Items();
items.setName(cursor.getString(0));
items.setScore(cursor.getString(1));
itemsList.add(items);
cursor.moveToNext();
}
}
//All done, so notify the adapter to populate the list using the Items Array
adapter.notifyDataSetChanged();
}
}
}
CustomListAdapter code
public class CustomListAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater inflater;
private List<Items> itemsItems;
public CustomListAdapter(Context context, List<Items> itemsItems) {
this.mContext = context;
this.itemsItems = itemsItems;
}
#Override
public int getCount() {
return itemsItems.size();
}
#Override
public Object getItem(int location) {
return itemsItems.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View scoreView, ViewGroup parent) {
ViewHolder holder;
if (inflater == null) {
inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
if (scoreView == null) {
scoreView = inflater.inflate(R.layout.list_row, parent, false);
holder = new ViewHolder();
holder.name = (TextView) scoreView.findViewById(R.id.name);
holder.score = (TextView) scoreView.findViewById(R.id.score);
scoreView.setTag(holder);
} else {
holder = (ViewHolder) scoreView.getTag();
}
final Items m = itemsItems.get(position);
holder.name.setText(m.getName());
holder.score.setText(m.getScore());
return scoreView;
}
static class ViewHolder {
TextView name;
TextView score;
}
}
Items Code
public class Items {
private String name, score;
public Items() {
}
public Items(String name, String score) {
this.name = name;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getScore() {
return score;
}
public void setScore(String score) {
this.score = score;
}
}
Couple of more things.
How to show the current Leaderboard using this code of Database?
I dont know how to use on that.
Use Google Play: https://developers.google.com/games/services/android/leaderboards
Create Google Play Game In Developer Console
1)Add the BaseGameUtils SDK from here https://github.com/playgameservices/android-basic-samples
2) In app gradle:
dependencies {
compile 'compile project(':BaseGameUtils')'
}
3) Update Score: Games.Leaderboards.submitScore(mGoogleApiClient, LEADERBOARD_ID, 1337);
4)
Display Leaderboard: startActivityForResult(Games.Leaderboards.getLeaderboardIntent(mGoogleApiClient,
LEADERBOARD_ID), REQUEST_LEADERBOARD);
Make sure you successfully connect to googleApiClient/Google Play Games Services

Android notifyDataSetChanged from a custom adapter

So my app uses a local SQLite db through a contentProvider
In it's mainActivity I have a listView displaying the contents of a table from the above DB.
I use a custom adapter to display the listview. Each item has a button in it's (custom) layout, that when pressed, shows a custom dialog that inserts a new record in that table, then the dialog gets dismissed.
In order to achieve this behavior, I placed the button click handler inside the customAdapter.
I would like to be able to refresh the listView after the inserting is done (so when dialog is dismissed)
How can I achieve this?
I should probably need to call notifyDataSetChanged somehow from inside the custom Adapter but I can't.
In short, my custom adapter looks like this:
public class DisplayStuffAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<String> id;
private ArrayList<String> iduser;
private ArrayList<String> product;
public DisplayStuffAdapter(Context c){
this.mContext = c;
}
public DisplayStuffAdapter(Context c, ArrayList<String> id, ArrayList<String> userid, ArrayList<String> product) {
this.mContext = c;
this.id = id;
this.userid = userid;
this.product = product;
}
public int getCount() {
return id.size();
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
public class Holder {
TextView txt_id;
TextView txt_userid;
TextView txt_prod;
}
public View getView(int pos, View child, ViewGroup parent) {
Holder mHolder;
LayoutInflater layoutInflater;
if (child == null) {
layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
child = layoutInflater.inflate(R.layout.myitem, null);
mHolder = new Holder();
mHolder.txt_id = (TextView) child.findViewById(R.id.tv_MkId);
mHolder.txt_userid = (TextView) child.findViewById(R.id.tv_MkUserId);
mHolder.txt_prod = (TextView) child.findViewById(R.id.tv_MkProduct);
child.setTag(mHolder);
} else {
mHolder = (Holder) child.getTag();
}
mHolder.txt_id.setText(id.get(pos));
mHolder.txt_userid.setText(userid.get(pos));
mHolder.txt_prod.setText(product.get(pos));
Button bt = (Button) child.findViewById(R.id.itemButton);
bt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
LayoutInflater li = LayoutInflater.from(mContext);
final View promptsView = li.inflate(R.layout.bid_dialog, null);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(mContext);
alertDialogBuilder.setView(promptsView);
alertDialogBuilder.setMessage("Input data")
.setIcon(R.drawable.add_red_24)
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
})
.setPositiveButton("Add new record", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
ContentValues values = new ContentValues();
values.put(MyProvider.TCOL_ID, myid);
values.put(MyProvider.TCOL_OTHERID, Integer.toString(getActiveUserId()));
Uri uri = mContext.getContentResolver().insert(MyProvider.CONTENT_URI_TABLE, values);
values = new ContentValues();
dialogInterface.dismiss();
}
}
}
});
// create alert dialog
final AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
alertDialog.setCanceledOnTouchOutside(false);
....
}
});
....
I remove some parts from the code to make it more readable.
Now, in my MainActivity, I set the adapter like this:
public class MainActivity extends Activity{
private ArrayList<String> id = new ArrayList<String>();
private ArrayList<String> userid = new ArrayList<String>();
private ArrayList<String> product = new ArrayList<String>();
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fillListView();
}
...
private void fillListView(){
id.clear();
userid.clear();
product.clear();
String[] col = {MyProvider.TCOL_ID_ID, MyProvider.TCOL_USERID, MyProvider.TCOL_PROD};
String where = "done = 1";
Cursor mCursor = MainActivity.this.getContentResolver().query(MyProvider.CONTENT_URI_TABLE, col, where, null, MyProvider.TCOL_DATE + " desc");
if (mCursor != null) {
if (mCursor.moveToFirst()) {
do {
id.add(Integer.toString(mCursor.getInt(0)));
userid.add(Integer.toString(mCursor.getInt(1)));
product.add(mCursor.getString(2));
} while (mCursor.moveToNext());
}
}
DisplayStuffAdapter disadpt = new DisplayStuffAdapter(MainActivity.this,id,userid,product);
disadpt.notifyDataSetChanged();
ListView lv = (ListView) findViewById(R.id.mylistView);
lv.setAdapter(disadpt);
}
So this all works great, except that when I add a new record to the table using the customdialog described above... the dialog closes, and the listview remains unchanged.
How can I refresh the listView?
In general, when you're querying data from a DB, you should use ContentProvider and CursorLoader. You can configure your content provider to automatically notify loaders when some data changes, using ContentResolver notifyChange() method. Place the call to this method in your ContentProvider implementation (for example after the insert). This is an example of adapter you can use (but you can use SimpleCursorAdapter providing a view binder too).
public class CustomCursorAdapter extends CursorAdapter {
private LayoutInflater mInflater;
public CustomCursorAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
if(cursor.getPosition()%2==1) {
view.setBackgroundColor(context.getResources().getColor(R.color.background_odd));
}
else {
view.setBackgroundColor(context.getResources().getColor(R.color.background_even));
}
TextView content = (TextView) view.findViewById(R.id.row_content);
content.setText(cursor.getString(cursor.getColumnIndex(Table.CONTENT)));
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mInflater.inflate(R.layout.listitem, parent, false);
}
}
public class DisplayStuffAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<String> id;
private ArrayList<String> iduser;
private ArrayList<String> product;
public DisplayStuffAdapter(Context c){
this.mContext = c;
}
public void loadData(){
id.clear();
userid.clear();
product.clear();
String[] col = {MyProvider.TCOL_ID_ID, MyProvider.TCOL_USERID, MyProvider.TCOL_PROD};
String where = "done = 1";
Cursor mCursor = MainActivity.this.getContentResolver().query(MyProvider.CONTENT_URI_TABLE, col, where, null, MyProvider.TCOL_DATE + " desc");
if (mCursor != null) {
if (mCursor.moveToFirst()) {
do {
id.add(Integer.toString(mCursor.getInt(0)));
userid.add(Integer.toString(mCursor.getInt(1)));
product.add(mCursor.getString(2));
} while (mCursor.moveToNext());
}
}
notifyDataSetChanged();
}
...
}
public class MainActivity extends Activity{
private DisplayStuffAdapter disadpt = null;
ContentObserver displayStuffObserver = new ContentObserver(new Handler()){
#Override
public void onChange(boolean selfChange) {
if(disadpt != null) {
disadpt.loadData();
}
}
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
disadpt = new DisplayStuffAdapter(this);
ListView lv = (ListView) findViewById(R.id.mylistView);
lv.setAdapter(disadpt);
disadpt.loadData();
getContentResolver().registerContentObserver(MyProvider.CONTENT_URI_TABLE,true, displayStuffObserver);
}
}
Do not forget to unregister your content observer
First of all, I am not getting why you are sending three different arraylists to the adapter. You can simply make a modal class having all the fields that you require in your adapter. Considering your current scenario it will be something like this
public class ModalClass {
private String id = "";
private String userId = "";
private String product = "";
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
}
So this is your modal class with getters and setters. Now all you have to do is you have to make an ArrayList of this modal class like this
List<ModalClass> modalClassList=new ArrayList<ModalClass>();
and you have to set all the data that you want to display in your list in this arraylist by making use of modal class setter functions. Like this
if (mCursor != null) {
if (mCursor.moveToFirst()) {
do {
ModalClass modalClass=new ModalClass();
modalClass.setId(Integer.toString(mCursor.getInt(0)));
modalClass.setUserId(Integer.toString(mCursor.getInt(1)));
modalClass.setProduct(mCursor.getString(2));
modalClassList.add(modalClass);
} while (mCursor.moveToNext());
}
}
and now you have your arraylist ready, so you can set it to your listview like this
ListView lv = (ListView) findViewById(R.id.mylistView);
DisplayStuffAdapter disadpt = new DisplayStuffAdapter(MainActivity.this,modalClassList);
lv.setAdapter(disadpt);
And accordingly you have to modify your adapter constructor which i think you can do by your own.
Also how to set values in your adapter, you can make use of your modal class getter methods like this.
ModalClass modalClass=modalClassList.get(pos);
mHolder.txt_id.setText(modalClass.getId());
mHolder.txt_userid.setText(modalClass.getUserId());
mHolder.txt_prod.setText(modalClass.getProduct());
Now when you want to insert a new row in your adapter, you have to simply create an object of ModalClass and set all the new values in that like we have done in our MainActivity class and then finally add that to your modalClassList followed by notifyDataSetChanged();
ModalClass modalClass=new ModalClass();
modalClass.setId(yourNewInsertedRowId);
modalClass.setUserId(yourNewInsertedRowUserId);
modalClass.setProduct(yourNewInsertedRowProduct);
modalClassList.add(modalClass);
notifyDataSetChanged();
And this time your list will be notify for sure. Cheers :)

Categories

Resources