I save my recyclerview with SQliteopenhelper . I use Itemtouchhelper and I can change items positions with itemtouchhelper on recycler view but I cant update positions on my database How Can I ?
todoactivity.java
public class todoactivity extends AppCompatActivity {
TextView title;
ImageButton gorevo;
RecyclerView recyclerView;
List<String>Listsx = new ArrayList<>();
TodoActivityAdpter adapterx;
DatabaseHelper4 myDBxxx;
TextView textView;
CheckBox checkBox;
long id;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_todoactivity);
recyclerView=findViewById(R.id.recyclerviewxx);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
adapterx=new TodoActivityAdpter(Listsx);
recyclerView.setAdapter(adapterx);
title=findViewById(R.id.titlex);
textView=findViewById(R.id.text_viewx);
gorevo = findViewById(R.id.gorevo);
myDBxxx = new DatabaseHelper4(this);
Cursor datax = myDBxxx.getListContents();
if(datax.getCount() == 0){
}else{
while(datax.moveToNext()){
Listsx.add(datax.getString(1));
ListAdapter listAdapterx = new ArrayAdapter<>(this,R.layout.todoactivity_item,R.id.textitem,Listsx);
adapterx.notifyItemInserted(Listsx.size()-1);
}
}
gorevo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(todoactivity.this);
bottomSheetDialog.setContentView(R.layout.bottomsheetlayout3);
bottomSheetDialog.show();
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED,0);
EditText editText = bottomSheetDialog.findViewById(R.id.editx);
Button ekle = bottomSheetDialog.findViewById(R.id.ekle);
ekle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String text = editText.getText().toString();
Listsx.add(text);
AddDataxxx(text);
adapterx.notifyItemInserted(Listsx.size()-1);
bottomSheetDialog.hide();
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(),0);
}
});
}
});
back=findViewById(R.id.back);
back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(todoactivity.this, pomodoroscreen.class);
startActivity(i);
overridePendingTransition(0,0);
}
});
ItemTouchHelper.SimpleCallback move = new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.START | ItemTouchHelper.END , 0) {
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
int fromPosition = viewHolder.getAdapterPosition();
int toPosition = target.getAdapterPosition();
Collections.swap(Listsx,fromPosition,toPosition);
recyclerView.getAdapter().notifyItemMoved(fromPosition,toPosition);
// I want update items position on my SQliteOpenhelper in there
return false;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
}
};
ItemTouchHelper itemTouchHelperx = new ItemTouchHelper(move);
itemTouchHelperx.attachToRecyclerView(recyclerView);
}
public void AddDataxxx(String newEntry) {
boolean insertDatax = myDBxxx.addDataxxx(newEntry);
}
}
DatabaseHelper.java
public class DatabaseHelper4 extends SQLiteOpenHelper {
public static final String DATABASE_NAME4 = "mylistxxx.db";
public static final String TABLE_NAME4 = "mylist_dataxxx";
public static final String COL14 = "iDxxx";
public static final String COL24 = "ITEM1xxx";
public DatabaseHelper4(Context context) {
super(context, DATABASE_NAME4, null, 1);
}
#Override
public void onCreate(SQLiteDatabase dbxxx) {
String createTable = "CREATE TABLE " + TABLE_NAME4 + " (iDxxx INTEGER PRIMARY KEY AUTOINCREMENT, " +
" ITEM1xxx TEXT)";
dbxxx.execSQL(createTable);
}
#Override
public void onUpgrade(SQLiteDatabase dbxxx, int oldVersion, int newVersion) {
dbxxx.execSQL("DROP IF TABLE EXISTS " + TABLE_NAME4);
onCreate(dbxxx);
}
public boolean addDataxxx(String textt) {
SQLiteDatabase dbxxx = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COL24, textt);
long result = dbxxx.insert(TABLE_NAME4, null, contentValues);
if (result == -1) {
return false;
} else {
return true;
}
}
public Cursor getListContents() {
SQLiteDatabase dbxxx = this.getWritableDatabase();
Cursor dataxxx = dbxxx.rawQuery("SELECT * FROM " + TABLE_NAME4, null);
return dataxxx;
}
}
Adapter.java
public class TodoActivityAdpter extends RecyclerView.Adapter<TodoActivityAdpter.Holder> {
List<String>Listsx;
public TodoActivityAdpter(List<String>itemxxx){
this.Listsx = itemxxx;
}
#NonNull
#Override
public TodoActivityAdpter.Holder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.todoactivity_item,parent,false);
Holder holder = new Holder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull TodoActivityAdpter.Holder holder, int position) {
holder.textView.setText(Listsx.get(position));
holder.checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (holder.checkBox.isChecked()) {
holder.textView.setTextColor(view.getResources().getColor(R.color.grey));
} else {
holder.textView.setTextColor(view.getResources().getColor(R.color.Color_black));
}
}
});
}
#Override
public int getItemCount() {
return Listsx.size();
}
public class Holder extends RecyclerView.ViewHolder {
CheckBox checkBox;
TextView textView;
List<String>Listsx;
RecyclerView recyclerView;
Context mContext;
public Holder(View view) {
super(view);
textView=view.findViewById(R.id.text_viewx);
checkBox=view.findViewById(R.id.checkbox);
recyclerView=view.findViewById(R.id.recyclerviewxx);
}
}
}
Thats my java classes . My activity is todoactivity . My SQliteopenhelper is DatabaseHelper.java . My Adapter is adapter.java . I can change items position on my recyclerview but ı cant update items position on my database . How can I
I suggest adding a column with the position to use for ordering.
Please close the cursor and return a list of objects. You can read your cursor using cursor.getString(cursor.getColumnIndex(colName)). Overriding close in your helper and closing the writableDatabase is also good practise. I myself open the writableDatabase only once (upon create) and close it at the end (upon close).
Regards, Mike
Related
I am creating a todo app with SQLite and RecyclerView, but I am having trouble in removing a task on a click of an image, which is my ivDelete. I want to delete completed tasks. any idea how to delete? any help would be appreciated.
This is my MainActivity:
public class MainActivity extends AppCompatActivity
{
Button btn_tasks,btn_reminders,btn_about;
ImageView img_addtask;
RecyclerView contactView;
DBHelper dbHelper;
CustomAdapter mAdapter;
private ArrayList<TaskClass> allContacts;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_tasks = findViewById(R.id.btn_task);
btn_reminders = findViewById(R.id.btn_reminder);
btn_about = findViewById(R.id.btn_about);
img_addtask = findViewById(R.id.imageView);
dbHelper = new DBHelper(this);
contactView = findViewById(R.id.list);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
contactView.setLayoutManager(layoutManager);
contactView.setHasFixedSize(true);
allContacts = new ArrayList<>();
allContacts = dbHelper.getTaskList();
loadTaskList();
img_addtask.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
addTask();
}
});
btn_reminders.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
addReminder();
}
});
}
private void loadTaskList()
{
ArrayList<TaskClass> taskList = dbHelper.getTaskList();
if(mAdapter == null)
{
contactView.setVisibility(View.VISIBLE);
mAdapter = new CustomAdapter(this,allContacts);
contactView.setAdapter(mAdapter);
}
else
{
contactView.setVisibility(View.GONE);
Toast.makeText(this, "There is no task in the database. Start
adding now", Toast.LENGTH_LONG).show();
}
}
private void addTask()
{
Intent intent = new Intent(this,AddTask.class);
startActivity(intent);
}
private void addReminder()
{
Intent intent = new Intent(this,AddReminder.class);
startActivity(intent);
}
}
This is my DBHelper Class:
public class DBHelper extends SQLiteOpenHelper
{
private static final String DB_NAME = "Demo.db";
private static final int DB_VER = 1;
private static final String DB_TABLE = "Task";
DBHelper(Context context)
{
super(context, DB_NAME, null, DB_VER);
}
#Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL(" CREATE TABLE " +DB_TABLE+" (ID INTEGER PRIMARY KEY AUTOINCREMENT, TaskName TEXT, dateStr TEXT)");
}
#Override
public void onUpgrade(SQLiteDatabase db, int i, int i1)
{
db.execSQL("DROP TABLE IF EXISTS "+DB_TABLE);
onCreate(db);
}
void insertNewTask(TaskClass taskClass)
{
ContentValues values = new ContentValues();
SQLiteDatabase db= this.getWritableDatabase();
values.put("TaskName",taskClass.getTaskName());
values.put("dateStr", taskClass.getTaskDate());
db.insert(DB_TABLE,null,values);
db.close();
}
public ArrayList<TaskClass> getTaskList()
{
String selectQuery = "SELECT * FROM " + DB_TABLE;
SQLiteDatabase db = this.getReadableDatabase();
ArrayList<TaskClass> taskList = new ArrayList<>();
Cursor cursor = db.rawQuery(selectQuery, null);
if(cursor.moveToFirst())
{
do {
String name = cursor.getString(cursor.getColumnIndex("TaskName"));
String date = cursor.getString(cursor.getColumnIndex("dateStr"));
taskList.add(new TaskClass(name,date));
}while (cursor.moveToNext());
}
cursor.close();
return taskList;
}
}
This is CustomAdapter Class:
public CustomViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_layout, parent, false);
return new CustomViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull CustomViewHolder viewHolder, final int position)
{
viewHolder.txtTask.setText(taskClass.get(position).getTaskName());
viewHolder.txtDate.setText(taskClass.get(position).getTaskDate());
}
#Override
public int getItemCount() {
return taskClass.size();
}
public class CustomViewHolder extends RecyclerView.ViewHolder
{
TextView txtTask,txtDate;
ImageView ivDelete;
public CustomViewHolder(View itemView)
{
super(itemView);
txtTask = itemView.findViewById(R.id.task_title);
txtDate = itemView.findViewById(R.id.task_date);
ivDelete = itemView.findViewById(R.id.ivDelete);
}
}
You can put a listener on your ivDelete in the onBindViewHolder of the adapter, and
delete the task by the id from the database. You will have to create a method to do so on the DBHelper class.
viewHolder.ivDelete.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Call method to delete task
}
});
When in SettingsActivity switch on to show only selected with checkbox and my List contains near 30 items, recyclerview scrolls normally, but when I use List with 900 items - recyclerview scrolls with freezes. Where my way to update recyclerview is wrong?
Android Studio log:
E/RecyclerView: No adapter attached; skipping layout
I/Choreographer: Skipped 68 frames! The application may be doing too much work on its main thread.
BikesAdapter:
public class BikesAdapter extends RecyclerView.Adapter<BikesAdapter.BikesViewHolder>{
private static final String PREFS_NAME = "bikes_prefs";
public static List<Categories> categories;
private Context context;
public BikesAdapter(Context context) {
this.context = context;
notifyDataSetChanged();
}
#Override
public BikesViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new BikesViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_bikes, parent, false));
}
#Override
public void onBindViewHolder(final BikesViewHolder holder, final int position) {
final SharedPreferences setFavoritesCnB = FragmentBikesListXT.context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
boolean isFavoriteChB = setFavoritesCnB.getBoolean(categories.get(position).title, false);
holder.cbStars.setChecked(isFavoriteChB);
holder.cbStars.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SharedPreferences.Editor editor = setFavoritesCnB.edit();
editor.putBoolean(categories.get(position).title, holder.cbStars.isChecked());
editor.apply();
if (holder.cbStars.isChecked()) {
openDBHelper.save(position);
Constants.CATEGORIES.add(categories.get(position));
} else {
openDBHelper.delete(position);
Constants.CATEGORIES.remove(categories.get(position));
}
}
});
if (checkSwitch) {
if (!isFavoriteChB) {
holder.cardView.setVisibility(View.GONE);
} else {
holder.textTitle.setText(categories.get(position).title);
}
} else holder.textTitle.setText(categories.get(position).title);
holder.textTitle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(categories.get(position).link));
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return categories.size();
}
public class BikesViewHolder extends RecyclerView.ViewHolder {
private CardView cardView;
private CheckBox cbStars;
private TextView textTitle;
public BikesViewHolder(View itemView) {
super(itemView);
cardView = (CardView) itemView.findViewById(R.id.cardView);
cbStars = (CheckBox) itemView.findViewById(R.id.cbStars);
textTitle = (TextView) itemView.findViewById(R.id.tv_title_bike);
}
}
}
Fragment with recyclerview:
public class FragmentBikesListXT extends Fragment {
public static RecyclerView rvBikes;
public static ProgressBar pbBikes;
public static Context context;
public static CreateDBHelper dbHelper;
public static OpenDBHelper openDBHelper;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
FrameLayout layout = (FrameLayout) inflater.inflate(R.layout.fragment_bikes_list_xt, container, false);
rvBikes = (RecyclerView) layout.findViewById(R.id.rvBikes);
pbBikes = (ProgressBar) layout.findViewById(R.id.pbBikes);
SharedPreferences setSwitch = getActivity().getSharedPreferences(PREFS_LIST, MODE_PRIVATE);
checkSwitch = setSwitch.getBoolean("NameOfThingToSave", false);
context = getContext();
dbHelper = new CreateDBHelper(this.getActivity());
openDBHelper = new OpenDBHelper();
initIO(Constants.URL_FULL_LIST);
return layout;
}
public void initIO(String url) {
ParseXT.initializeData(url);
rvBikes.setHasFixedSize(true);
rvBikes.setLayoutManager(new GridLayoutManager(this.getActivity(), 1));
}
}
SettingsActivity:
public class SettingsActivity extends AppCompatActivity {
private Switch mSwitch;
public static boolean checkSwitch;
public static final String PREFS_LIST = "list_prefs";
public static Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
mSwitch = (Switch) findViewById(R.id.switch_list);
SharedPreferences setSwitch = getSharedPreferences(PREFS_LIST, MODE_PRIVATE);
mSwitch.setChecked(setSwitch.getBoolean("NameOfThingToSave", false));
mSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
if(isChecked){
checkSwitch = true;
SharedPreferences.Editor editor = getSharedPreferences(PREFS_LIST, MODE_PRIVATE).edit();
editor.putBoolean("NameOfThingToSave", true);
editor.commit();
}else{
checkSwitch = false;
SharedPreferences.Editor editor = getSharedPreferences(PREFS_LIST, MODE_PRIVATE).edit();
editor.putBoolean("NameOfThingToSave", false);
editor.commit();
}
}
});
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
super.onBackPressed();
return true;
}
finish();
return super.onOptionsItemSelected(item);
}
}
OpenDBHelper:
public class OpenDBHelper implements IDBHelper {
private SQLiteDatabase db;
#Override
public void read() {
db = FragmentBikesListXT.dbHelper.getWritableDatabase();
BikesAdapter.categories.clear();
Cursor c = db.query(Constants.TABLE_BIKE, null, null, null, null, null, null);
if (c.moveToFirst()) {
int titleColIndex = c.getColumnIndex(Constants.FIELD_TITLE);
int linkColIndex = c.getColumnIndex(Constants.FIELD_LINK);
do {
BikesAdapter.categories.add(new Categories(
c.getString(titleColIndex),
c.getString(linkColIndex)));
Log.d("DBHelper", "READ ID = " + c.getString(titleColIndex));
} while (c.moveToNext());
} else
c.close();
}
#Override
public void save(int position) {
ContentValues cv = new ContentValues();
db = FragmentBikesListXT.dbHelper.getWritableDatabase();
cv.put(Constants.FIELD_TITLE, BikesAdapter.categories.get(position).title);
cv.put(Constants.FIELD_LINK, BikesAdapter.categories.get(position).link);
long size = db.insert(Constants.TABLE_BIKE, null, cv);
Log.d("DBHelper", "SAVE row inserted, size " + size + " ID = , " + BikesAdapter.categories.get(position).title);
FragmentBikesListXT.dbHelper.close();
}
#Override
public void delete(int position) {
db = FragmentBikesListXT.dbHelper.getWritableDatabase();
String[] whereArgs = {String.valueOf(BikesAdapter.categories.get(position).title)};
db.delete(Constants.TABLE_BIKE, Constants.FIELD_TITLE + " = ?", whereArgs);
Log.d("DBHelper", "DELETE ID = " + BikesAdapter.categories.get(position).title);
db.close();
}
}
And parser class:
public class ParseXT {
private static Elements titleTxt;
private static Elements linkTxt;
private static ArrayList<String> titleList = new ArrayList<>();
private static ArrayList<String> linkList = new ArrayList<>();
public static BikesAdapter bikesAdapter = new BikesAdapter(FragmentBikesListXT.context);
public static void initializeData(String url) {
new NewTreadParsed(url).execute();
}
public static class NewTreadParsed extends AsyncTask<List<Categories>, Void, List<Categories>> {
private String url;
public NewTreadParsed(String url) {
this.url = url;
}
#Override
protected List<Categories> doInBackground(List<Categories>... params) {
Document doc;
List<Categories> categories = new ArrayList<>();
try {
doc = Jsoup.connect(url).get();
titleTxt = doc.select(".topictitle");
linkTxt = doc.select(".a[href]");
titleList.clear();
linkList.clear();
for (Element contents : titleTxt) {
titleList.add(contents.text());
}
for (Element contents1 : titleTxt) {
Element element = contents1.select("a[href]").first();
linkList.add(element.attr("abs:href"));
}
}
catch (IOException e){
e.printStackTrace();
}
for (int i = 0; i < titleList.size(); i++) {
categories.add(new Categories(titleList.get(i), linkList.get(i)));
}
return categories;
}
#Override
protected void onPostExecute(List<Categories> categories) {
super.onPostExecute(categories);
FragmentBikesListXT.pbBikes.setVisibility(ProgressBar.INVISIBLE);
BikesAdapter.categories = categories;
FragmentBikesListXT.rvBikes.setAdapter(bikesAdapter);
}
}
}
Use notifyDataSetChanged()
If you are writing an adapter it will always be more efficient to use the more specific change events if you can. Rely on notifyDataSetChanged()
I have a recyclerview inside a fragment activity that uses a button to bring up an alert dialog box to get input for 2 string variables. I have successfully created the database and can add items to the database from the alertdialog input, but I want to populate the recyclerview with the database when the app initially starts up. The database is used to store the input and I want it to populate the recyclerview so the user can see the items they entered previously.
This is my fragment:
public class tab1Expenses extends Fragment {
SqlDatabase dbEntry;
ArrayList<ExRow> expenseList = new ArrayList<>();
RecyclerView recyclerView;
ExpensesAdapter mAdapter;
Button btnEx;
String Na;
String Am;
String message = "Name must be longer than 2 characters";
String message2 = "Please enter valid amount";
Double value;
String am;
public void expenseData() {
ExRow exs = new ExRow(Na, Am);
expenseList.add(exs);
mAdapter.notifyDataSetChanged();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final View rootView = inflater.inflate(R.layout.tab1expense, container, false);
btnEx = (Button) rootView.findViewById(R.id.btnEx);
recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
recyclerView.addItemDecoration(new DividerItemDecoration(tab1Expenses.this.getActivity(), LinearLayoutManager.VERTICAL));
mAdapter = new ExpensesAdapter(expenseList);
final RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this.getActivity());
recyclerView.setHasFixedSize(true);
recyclerView.setClickable(true);
recyclerView.isFocusable();
recyclerView.setFocusableInTouchMode(true);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
btnEx.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Brings up Alert Dialog when Add income button is pressed
add();
}
});
return rootView;
}
public int add() {
View view = LayoutInflater.from(tab1Expenses.this.getActivity())
.inflate(R.layout.add_ex, null);
final EditText txtExName = (EditText) view.findViewById(R.id.exName);
final EditText txtExAmount = (EditText) view.findViewById(R.id.exAmount);
//Creates Alert Dialog
AlertDialog.Builder add = new AlertDialog.Builder(tab1Expenses.this.getActivity());
add.setCancelable(true)
.setTitle("Enter Expense:")
.setView(view)
.setPositiveButton("Add",
//AlertDialog positive button ClickListener
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//Checks for invalid input
//If criteria met, expenseData() is called
if (txtExAmount.getText().length() > 0 && txtExName.getText().length() > 2 && txtExAmount.getText().length() < 6 && txtExName.getText().length() < 25) {
Na = txtExName.getText().toString();
am = txtExAmount.getText().toString();
value = Double.parseDouble(am);
Am = NumberFormat.getCurrencyInstance().format(value);
expenseData();
}
//Toast for invalid input
if (txtExName.getText().length() <= 2) {
Toast.makeText(tab1Expenses.this.getActivity(), message, Toast.LENGTH_SHORT).show();
} else if (txtExAmount.getText().length() == 0) {
Toast.makeText(tab1Expenses.this.getActivity(), message2, Toast.LENGTH_SHORT).show();
} else if (txtExAmount.getText().length() >= 6) {
Toast.makeText(tab1Expenses.this.getActivity(), "You don't make that much", Toast.LENGTH_SHORT).show();
} else if (txtExName.getText().length() >= 25) {
Toast.makeText(tab1Expenses.this.getActivity(), "Name must be less than 25 characters", Toast.LENGTH_SHORT).show();
}
}
});
Dialog dialog = add.create();
dialog.show();
return 0;
}
public void viewAll() {
ExRow exrow = new ExRow();
Cursor res = dbEntry.getAllData();
exrow.setTitle(res.getString(1));
exrow.setAmount(res.getString(2));
}
}
This is my database:
public class SqlDatabase extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "Expenses.db";
public static final String TABLE_NAME = "Expense_Table";
public static final String ID = "id";
public static final String Col_NAME = "Na";
public static final String Col_AMOUNT = "Am";
public SqlDatabase(Context context) {
super(context, DATABASE_NAME, null, 1);
}
#Override
//Set up database here
public void onCreate(SQLiteDatabase db) {
db.execSQL("Create table " + TABLE_NAME +
"(ID INTEGER PRIMARY KEY AUTOINCREMENT,NAME TEXT, AMOUNT TEXT)");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
public boolean insertData(String Na, String Am) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(Col_NAME, Na);
contentValues.put(Col_AMOUNT, Am);
long result = db.insert(TABLE_NAME, null, contentValues);
if (result == -1) {
return false;
} else {
return true;
}
}
public static Cursor getAllData() {
SQLiteDatabase db = this.getWritableDatabase();
Cursor res = db.rawQuery("select * from " + TABLE_NAME, null);
return res;
}
}
And this is my RecyclerView Adapter + View holder:
public class ExpensesAdapter extends RecyclerView.Adapter<ExpensesAdapter.MyViewHolder> {
public ImageButton mRemoveButton;
private ArrayList<ExRow> expenseList;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title, amount;
public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.name);
amount = (TextView) view.findViewById(R.id.amount);
mRemoveButton = (ImageButton) view.findViewById(R.id.ib_remove);
}
}
public ExpensesAdapter(ArrayList<ExRow> expenseList) {
this.expenseList = expenseList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.expense_list, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, int position
) {
ExRow expense = expenseList.get(holder.getAdapterPosition());
holder.title.setText(expense.getTitle());
holder.amount.setText(expense.getAmount());
mRemoveButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
// Remove the item on remove/button click
int adapterPosition = holder.getAdapterPosition();
expenseList.remove(adapterPosition);
notifyItemRemoved(adapterPosition);
notifyDataSetChanged();
}
});
}
#Override
public int getItemCount() {
return expenseList.size();
You need to get List of your ExRow instead of cursor in your SQLiteOpenHelper. So instead of:
public static Cursor getAllData() {
SQLiteDatabase db = this.getWritableDatabase();
Cursor res = db.rawQuery("select * from " + TABLE_NAME, null);
return res;
}
You need to return List with something like this:
// Your column
private String[] allColumns = { "ID", "COLUMN_1", "COLUMN_2" };
public List<ExRow> getAllData() {
List<ExRow> exrows = new ArrayList<>();
Cursor cursor = database.query("YOUR_TABLE", allColumns, null, null,
null, null, null);
if (cursor != null && cursor.moveToFirst()) {
while (!cursor.isAfterLast()) {
ExRow exrow = populateModel(cursor);
exrows.add(exrow);
cursor.moveToNext();
}
cursor.close();
}
return exrows;
}
private ExRow populateModel(Cursor c) {
ExRow model = new ExRow();
model.setId(c.getLong("ID"));
model.setColumn1(c.getString(c.getColumnIndex("COLUMN_1")));
model.setColumn2(c.getString(c.getColumnIndex("COLUMN_2")));
return model;
}
Then you can use the value returned from getAllData() and pass it to your Adapter.
Adding and removing items from RecyclerView is working, but i don't know if i have written a good method in database for deleting rows because only i'm saving condition when item is added and when it is removed and if i leave from app and come back, but previosly i have deleted some items, i'm seeing them there. So i need some help about this method in database for removing items and also implementing it in activity.
Here are my code:
DATABASE:
public class DBHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "items.db";
private static final int DATABASE_VERSION = 1;
private final String TABLE_ITEMS = "items";
private final String COLUMN_ID = "id";
private final String COLUMN_ITEM = "item";
private static DBHelper dbh;
private DBHelper(Activity activity) {
super(activity, DATABASE_NAME, null, DATABASE_VERSION);
}
public static synchronized DBHelper getConnection(Activity activity) {
if (dbh == null)
dbh = new DBHelper(activity);
return dbh;
}
#Override
public void onCreate(SQLiteDatabase db) {
String upitZaPravljanjeBaze =
"CREATE TABLE "+TABLE_ITEMS+"("+COLUMN_ID+" INTEGER PRIMARY KEY, "+COLUMN_ITEM+" TEXT);";
db.execSQL(upitZaPravljanjeBaze);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion > oldVersion) {
db.execSQL("DROP TABLE" + "TABLE_ITEMS");
onCreate(db);
}
}
public ArrayList<String> getAllItems() {
ArrayList<String> toRet = new ArrayList<String>();
SQLiteDatabase db = getReadableDatabase();
Cursor c = db.rawQuery("SELECT * FROM " + TABLE_ITEMS, null);
c.moveToFirst();
while(c.isAfterLast() == false) {
toRet.add(c.getString(c.getColumnIndex(COLUMN_ITEM)));
c.moveToNext();
}
return toRet;
}
public long saveItem(String item) {
SQLiteDatabase db = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(COLUMN_ITEM, item);
return db.insert(TABLE_ITEMS, null, cv);
}
public boolean deleteItem(long rowId) {
SQLiteDatabase db = getReadableDatabase();
return db.delete(TABLE_ITEMS, COLUMN_ID + "=" + rowId, null) > 0;
}
}
ADAPTER:
public class AdapterRecyclerAnimators extends RecyclerView.Adapter<AdapterRecyclerAnimators.Holder> {
private ArrayList<String> mListData = new ArrayList<>();
private LayoutInflater mLayoutInflater;
public AdapterRecyclerAnimators(Context context) {
mLayoutInflater = LayoutInflater.from(context);
}
#Override
public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
View row = mLayoutInflater.inflate(R.layout.custom_row_item, parent, false);
Holder holder = new Holder(row);
return holder;
}
#Override
public void onBindViewHolder(Holder holder, final int position) {
String data = mListData.get(position);
holder.textDataItem.setText(data);
holder.buttonDelete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
removeItem(position);
}
});
}
public void addItem(String item) {
mListData.add(item);
notifyItemInserted(mListData.size());
}
public void addAll(ArrayList<String> newList){
mListData = newList;
notifyDataSetChanged();
}
public void removeItem(String item) {
int position = mListData.indexOf(item);
if (position != -1) {
mListData.remove(item);
notifyItemRemoved(position);
}
}
public void removeItem(int position) {
mListData.remove(position);
notifyItemRemoved(position);
}
#Override
public int getItemCount() {
return mListData.size();
}
public static class Holder extends RecyclerView.ViewHolder {
TextView textDataItem;
ImageButton buttonDelete;
public Holder(View itemView) {
super(itemView);
textDataItem = (TextView) itemView.findViewById(R.id.text_item);
buttonDelete = (ImageButton) itemView.findViewById(R.id.button_delete);
}
}
}
MAIN ACTIVITY:
public class MainActivity extends BaseActivity {
//int containing the duration of the animation run when items are added or removed from the RecyclerView
public static final int ANIMATION_DURATION = 2000;
//edit text letting the user type item name to be added to the recylcerview
private EditText mInput;
//itemcounter for recyclerview
private TextView mItemCounter;
//recyclerview showing all items added by the user
private RecyclerView mRecyclerView;
private AdapterRecyclerAnimators mAdapter;
ArrayList<String> mListData = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initViews();
if(savedInstanceState != null){
ArrayList<String> items = savedInstanceState.getStringArrayList("items");
mListData.addAll(items);
mAdapter.notifyDataSetChanged();
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putStringArrayList("items", mListData);
}
private void initViews(){
mInput = (EditText) findViewById(R.id.text_input);
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerAnimatedItems);
mItemCounter = (TextView) findViewById(R.id.itemCounter);
mItemCounter.setText(String.valueOf(mRecyclerView.getChildCount()));
mAdapter = new AdapterRecyclerAnimators(this);
//set an animator on the RecyclerView that works only when items are added or removed
mRecyclerView.setItemAnimator(new SlideInLeftAnimator());
mRecyclerView.getItemAnimator().setAddDuration(ANIMATION_DURATION);
mRecyclerView.getItemAnimator().setRemoveDuration(ANIMATION_DURATION);
mAdapter.addAll(DBHelper.getConnection(MainActivity.this).getAllItems());
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
}
public void addItem(View view) {
//check if the EditText has valid contents
if (Util.hasValidContents(mInput)) {
DBHelper.getConnection(MainActivity.this)
.saveItem(mInput.getText().toString());
ArrayList<String> allItems = DBHelper.getConnection(MainActivity.this).getAllItems();
mAdapter.addAll(allItems);
mInput.setText("");
}
}
#Override
protected int getLayoutResourceId() {
return R.layout.activity_main;
}
#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);
}
}
These are your delete methode:
public void removeItem(String item) {
int position = mListData.indexOf(item);
if (position != -1) {
mListData.remove(item);
notifyItemRemoved(position);
}
}
public void removeItem(int position) {
mListData.remove(position);
notifyItemRemoved(position);
}
You remove the items from your list but you never remove them from your database. Call your delete method in both of of these methods and see if it works.
Don't necessarily think this will fix your problem but thought I would point it out, In your database delete method you have:
SQLiteDatabase db = getReadableDatabase();
You probably want to switch that:
SQLiteDatabase db = getWritableDatabase();
My app has a RecyclerView/CardView of Tasks. Each card is populated by my adapter with getAllTasksForUser() in my TaskTableController class:
public List<Task> getAllTasksForUser() {
final String QUERY_ALL_RECORDS = "SELECT * FROM " + TaskEntry.TABLE_NAME;
List<Task> taskList = new ArrayList<>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(QUERY_ALL_RECORDS, null);
if (cursor.getCount() > 0) {
while (cursor.moveToNext()) {
Task task = new Task();
int TaskId = cursor.getColumnIndex(TaskEntry.COLUMN_TASK_ID);
task.setId(cursor.getString(TaskId));
task.setTitle(cursor.getString(cursor.getColumnIndex(TaskEntry.COLUMN_TASK_TITLE)));
task.setDue(new DateTime(cursor.getString(cursor.getColumnIndex(TaskEntry.COLUMN_TASK_DUE))));
task.setNotes(cursor.getString(cursor.getColumnIndex(TaskEntry.COLUMN_TASK_NOTES)));
task.setStatus(cursor.getString(cursor.getColumnIndex(TaskEntry.COLUMN_TASK_STATUS)));
taskList.add(task);
}
} else {
cursor.close();
db.close();
return taskList;
}
cursor.close();
db.close();
return taskList;
}
which is used to populate a ListArray of Task objects in my Adapter.
public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.TaskViewHolder> {
private List<Task> taskList;
OnItemClickListener mItemClickListener;
public TaskAdapter(List<Task> taskList) {
this.taskList = taskList;
}
#Override
public int getItemCount() {
return taskList.size();
}
#Override
public void onBindViewHolder(TaskViewHolder taskViewHolder, int i) {
Task task = taskList.get(i);
taskViewHolder.mTitle.setText(task.getTitle());
taskViewHolder.mDue.setText(task.getDue().toString());
if (task.getStatus().equals("completed")) {
taskViewHolder.mStatus.setChecked(true);
} else taskViewHolder.mStatus.setChecked(false);
}
#Override
public TaskViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext()).
inflate(R.layout.tasklist_layout, viewGroup, false);
return new TaskViewHolder(itemView);
}
public void SetOnItemClickListener(final OnItemClickListener mItemClickListener) {
this.mItemClickListener = mItemClickListener;
}
public interface OnItemClickListener {
void onItemClick(View view , int position);
}
And subsequently in my MainActivity with
taskAdapter = new TaskAdapter(new TaskTableController(getActivity()).getAllTasksForUser());
return rootView;
My question is, once one of these items is clicked, how can I retrieve the sqlite _ID or another unique identifier to used as an input for a more detailed query which is called in another Activity/fragment (i'm not sure which one). I've tried by adding in the MainActivity
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mRecyclerView.setAdapter(taskAdapter);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
taskAdapter.SetOnItemClickListener(new TaskAdapter.OnItemClickListener() {
#Override
public void onItemClick(View v, int position) {
m_ID = (TextView) v.findViewById(R.id._task_id);
Intent detailIntent = new Intent(v.getContext(), DetailActivity.class);
detailIntent.putExtra("TASK_ID", m_ID.getText().toString());
startActivity(detailIntent);
}
});
}
In my TaskTableController class i've added another method
public Task getTaskByID(String Id) {
final String SINGLE_TASK_QUERY = "SELECT * FROM " + TaskEntry.TABLE_NAME +
" WHERE " + TaskEntry._ID + " = " + Id;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(SINGLE_TASK_QUERY, null);
Task task = new Task();
while (cursor.moveToNext()){
task.setId(cursor.getString(cursor.getColumnIndex(TaskEntry.COLUMN_TASK_ID)));
task.setTitle(cursor.getString(cursor.getColumnIndex(TaskEntry.COLUMN_TASK_TITLE)));
task.setDue(new DateTime(cursor.getString(cursor.getColumnIndex(TaskEntry.COLUMN_TASK_DUE))));
task.setNotes(cursor.getString(cursor.getColumnIndex(TaskEntry.COLUMN_TASK_NOTES)));
}
return task;
}
should I call getTaskByID() in my DetailActivity or my DetailFragment which is responsible for inflating the detailed view? And how do I pass the ID from the intent extra to the query method?
This is how I do it most times:
1.In the constructor of your adapter, add an parameter (OnClickListener interface) and save it as an attribute in your custom adapter class.
2.In your onCreateViewHolder method, add to your view this click listener (implemented, for instance, in your Activity o fragment).In your case:
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listClickListener.onClick(v);
}
});
3.Implement this method, getting the position clicked from the RecyclerView getChildPosition.
#Override
public void onClick(View view) {
int itemPosition = recyclerView.getChildPosition(view);
//With the position you should be able to get the object you want to extract from your adapter.
}
I hope this would help man.
Right answer from Juan Aguilar Guisado and for example in RecycleviewAdapter
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Picasso.with(mContext).load(R.drawable.add2new).into(holder.image);
holder.text.setText(mDataSet.get(position));
holder.askprice.setText(mAskPrice.get(position));
holder.bidprice.setText(mBidPrice.get(position));
holder.profit.setText(mProfit.get(position));
holder.setClickListener(new FavoriteAdapter.ViewHolder.ClickListener() {
public void onClick(View v, int pos, boolean isLongClick) {
if (isLongClick) {
// View v at position pos is long-clicked.
String poslx = pos + "";
Toast.makeText(mContext, "longclick " + poslx, Toast.LENGTH_SHORT).show();
} else {
// View v at position pos is clicked.
String possx = pos + "";
Toast.makeText(mContext, "shortclick " + possx, Toast.LENGTH_SHORT).show();
//toggleSelection(pos);
}
}
});
}
and in ViewHolder
static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
public ImageView image;
public TextView text;
public TextView askprice;
public TextView bidprice;
public TextView profit;
private ClickListener clickListener;
public ViewHolder(View itemView) {
super(itemView);
image = (ImageView) itemView.findViewById(R.id.image);
text = (TextView) itemView.findViewById(R.id.text);
askprice = (TextView) itemView.findViewById(R.id.askprice);
bidprice = (TextView) itemView.findViewById(R.id.bidprice);
profit = (TextView) itemView.findViewById(R.id.profit);
// We set listeners to the whole item view, but we could also
// specify listeners for the title or the icon.
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
/* Interface for handling clicks - both normal and long ones. */
public interface ClickListener {
/**
* Called when the view is clicked.
*
* #param v view that is clicked
* #param position of the clicked item
* #param isLongClick true if long click, false otherwise
*/
public void onClick(View v, int position, boolean isLongClick);
}
/* Setter for listener. */
public void setClickListener(ClickListener clickListener) {
this.clickListener = clickListener;
}
#SuppressWarnings("deprecation")
#Override
public void onClick(View v) {
// If not long clicked, pass last variable as false.
clickListener.onClick(v, getPosition(), false);
}
#SuppressWarnings("deprecation")
#Override
public boolean onLongClick(View v) {
// If long clicked, passed last variable as true.
clickListener.onClick(v, getPosition(), true);
return true;
}
}
#Override
public TaskViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext()).
inflate(R.layout.tasklist_layout, viewGroup, false);
TaskViewHolder viewHolder = new TaskViewHolder(itemView);
viewHolder.itemView.setClickable(true);
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (taskListCallbacks != null)
taskListCallbacks.onTaskClick(taskList.get(viewHolder.getAdapterPosition()), v, viewHolder.getAdapterPosition());
}
});
return viewHolder;
}
public void setTaskListCallbacks(TaskListCallbacks taskListCallbacks){
this.taskListCallbacks = taskListCallbacks;
}
public interface TaskListCallbacks{
void onTaskClick(Task task, View v, int position);
}