We can show all records in the DB no issue. When we try to limit the items to show with a sql Select the search and the RecyclerView Adapter populates correctly.
The code fails when the item is selected in the list view. The list view did not get the message about what position this record is at so the view when we navigate to the DetailActivity view from ListActivity is not the item in the ListView
My question is how to manage the position variable that the Adapter is using?
This code flow is as follows a button click on MainActivity sets the search variable goes to ListActivity that makes a call to DBHelper which returns to ListActivity with modelList which is and Array List Yes the design is MVP so we have a Model Class relevant code below
Main Activity btn Click
public void findAllData(View view){
selectSTRING = etFromDate.getText().toString();
Intent intent = new Intent( MainActivity.this, ListActivity.class );
startActivity( intent );
}
ListActivity call to DBHelper commented out line gets all data
helpher = new DBHelper(this);
dbList = new ArrayList<>();
dbList = helpher.getRangeDataFromDB();
//dbList = helpher.getDataFromDB();
DBHelper code to grab the selected record or records eventually
public List<DBModel> getRangeDataFromDB() {
List<DBModel> modelList = new ArrayList<>();
db = this.getReadableDatabase();
String query = "SELECT * FROM " + TABLE_INFO + " WHERE " + Col_PURCHASE_DATE + " ='" + selectSTRING + "'";
Cursor cursor = db.rawQuery(query, null);
//Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_INFO + " WHERE " + Col_PURCHASE_DATE + "='" + str + "'" , null);
String newBACK = selectSTRING;
if (cursor.moveToFirst()) {
DBModel model = new DBModel();
while (!cursor.isAfterLast()) {
if (newBACK == selectSTRING) {
model.setRowid(cursor.getString(0));
model.setStation_Name(cursor.getString(1));
model.setDate_of_Purchase(cursor.getString(2));
model.setGas_Cost(cursor.getString(3));
modelList.add(model);
cursor.moveToNext();
}
}
}
int sz = modelList.size();
System.out.println("========= SIZE "+sz);
db.close();
return modelList;
}
Now we use an intent to go to DetailsActivity and this is the fail
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
static List<DBModel> dbList;
static private Context context;
RecyclerAdapter(Context context, List<DBModel> dbList) {
RecyclerAdapter.dbList = new ArrayList<>();
RecyclerAdapter.context = context;
RecyclerAdapter.dbList = dbList;
}
#Override
public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_row, null);
// create ViewHolder
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
}
#Override
public void onBindViewHolder(RecyclerAdapter.ViewHolder holder, int position) {
holder.rowid.setText(dbList.get(position).getRowid());
holder.station.setText(dbList.get(position).getStation_Name());
System.out.println("========== new position "+position);
}
#Override
public int getItemCount() {
return dbList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView station, rowid;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
rowid = (TextView) itemLayoutView.findViewById(R.id.rvROWID);
station = (TextView) itemLayoutView.findViewById(R.id.rvSTATION);
// Attach a click listener to the entire row view
itemLayoutView.setOnClickListener(this);
}
#Override // When an item in DetailsActivity is touched (selected) the RecyclerView has
// a OnClickListener attached in the above Code that implements the method below
public void onClick(View v) {
System.out.println("======RowID "+rowid);
Intent intentN = new Intent(context, DetailsActivity.class);
Bundle extras = new Bundle();
extras.putInt("POSITION", getAdapterPosition());
extras.putString("FROM_LIST_ACTIVITY", "false");
///position = getAdapterPosition();
///position = getLayoutPosition();// Both work the same
intentN.putExtras(extras);
context.startActivity(intentN);
}
}
Thought about sending the data back from the DBHelper not sure how to write an Intent in that Class. This is turning into spaghetti code!
The solution to this issue is the developer had multiple search designs in the DBHelper each being triggered by different buttons on the search Activity this design in the DBHelper lead to multiple ArrayLists all with the same name this drove the RecycleAdapter crazy as it is bound to ArrayList so OLD Mr. Boolean to the rescue! Here is the revised design code features
In the Search Activity declare public static Boolean use = false;
and Import where needed import static com..MainActivity.use;
Here is the code for each search button
public void findAllData(View view){
helper = new DBHelper(this);
helper.getDataFromDB();
use = false;
// Set Mr. Boolean
Intent intent = new Intent( MainActivity.this, ListActivity.class );
// ListActivity shows Results of the Search
startActivity( intent );
}
public void findSelect(View v){
selectSTRING = etFromDate.getText().toString();
// Get your Search variable
helper = new DBHelper(this);
helper.getDataFromDB();
etToDate.setText(sendBACK);
use = true;
Intent intent = new Intent( MainActivity.this, ListActivity.class );
startActivity( intent );
}
Now we do the desired Search in DBHelper
/* Retrive ALL data from database table named "TABLE_INFO" */
public List<DBModel> getDataFromDB(){
//String query = "SELECT * FROM " + TABLE_INFO + " WHERE " + Col_PURCHASE_DATE + " > 0 " + " ORDER BY " + Col_ID + " DESC ";
/* Notice the SPACES before AND after the words WHERE ORDER BY ASC or DESC most of all the condition " > 0 "*/
/* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=*/
Cursor cursor = null;
List<DBModel> modelList = new ArrayList<>();
if(use == true){
String query = "SELECT * FROM " + TABLE_INFO + " WHERE " + Col_PURCHASE_DATE + " ='" + selectSTRING + "'";
db = this.getWritableDatabase();
cursor = db.rawQuery(query,null);
}
if(use == false){
String query = "SELECT * FROM " + TABLE_INFO;
db = this.getWritableDatabase();
cursor = db.rawQuery(query,null);
}
if (cursor.moveToFirst()){
do {
DBModel model = new DBModel();
model.setRowid(cursor.getInt(0));
model.setStation_Name(cursor.getString(1));
model.setDate_of_Purchase(cursor.getString(2));
model.setGas_Cost(cursor.getString(3));
modelList.add(model);
int sz = modelList.size();
int out = model.setRowid(cursor.getInt(0));
String out1 = model.setStation_Name(cursor.getString(1));
String out2 = model.setDate_of_Purchase(cursor.getString(2));
String out3 = model.setGas_Cost(cursor.getString(3));
System.out.println("==============getDataFromDB ID "+out);
System.out.println("==============getDataFromDB Station "+out1);
System.out.println("==============getDataFromDB Date "+out2);
System.out.println("==============getDataFromDB Cost "+out3);
System.out.println("======= ======getDataFromDB SIZE "+sz);
}while (cursor.moveToNext());
}
db.close();
cursor.close();
return modelList;
}
The only stumble with this is that if if you do a search by date and do an add to the DB and jump back to the ListActivity the new record is not displayed
We are working on this Stay Tuned ha ha Good Job James_Duh
You should set your OnClickListener here :
#Override
public void onBindViewHolder(ReportAdapter.ViewHolderReport holder, int position) {
final Object object = objects.get(position);
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Do Something with the object at this position
}
});
}
instead of your ViewHolder because you shouldn't trust the adapter position at a time.
Related
This question has been asked before but none of the implementations helped me so far.
I'm building a to do app and I'm displaying my items in a listview, using SQLite for persistence. I'm able to dynamically add items to my listview and successfully store them in my database, but I'm not able to delete them from the screen or the table. I know the reason why. My SQLite Row ID does not match my ListView. But the other problem is that I should still be able to delete items off my screen and my table with positions that does match the SQLite Row ID (For example, my 3rd To Do in the list) but I'm not able to delete anything.
This is my method that is supposed to delete items from the database:
public boolean itemDeleteFromDatabase(long id) {
SQLiteDatabase database = databaseHelper.getWritableDatabase();
boolean databaseDelete = database.delete(TABLE_NAME, TO_DO + "=?" + id, null) > 0;
listItems.setAdapter(adapter);
return databaseDelete;
}
And I'm calling this method from my OnItemLongClick method, passing in the ListView position as the parameter:
listItems.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> adapter, View item, int position, long id) {
toDoItems.remove(position);
itemDeleteFromDatabase(id);
MainActivity.this.adapter.notifyDataSetChanged();
return true;
}
});
This is the stacktrace. The problem with this is that it only addresses 1 problem in the code:
FATAL EXCEPTION: main
Process: ca.ozbek.preworktodoapp, PID: 2105
android.database.sqlite.SQLiteException: variable number must be between ?1 and ?999 (code 1): , while compiling: DELETE FROM student WHERE todo=?0
Adding Source Code per request
MainActivity.java
public class MainActivity extends AppCompatActivity {
DatabaseHelper databaseHelper;
private final int REQUEST_CODE = 10;
ArrayList <String> toDoItems = new ArrayList<>();
ArrayAdapter<String> adapter;
ListView listItems;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listItems = (ListView) findViewById(R.id.listViewItems);
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, toDoItems);
listItems.setAdapter(adapter);
databaseHelper = new DatabaseHelper(this);
getToDos();
listItems.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> adapter, View item, int position, long id) {
toDoItems.remove(position);
itemDeleteFromDatabase(id + 1);
MainActivity.this.adapter.notifyDataSetChanged();
return true;
}
});
listItems.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapter, View item, int pos, long id) {
Intent intent = new Intent(MainActivity.this, EditItemActivity.class);
intent.putExtra("item", toDoItems.get(pos));
intent.putExtra("itemPos", String.valueOf(pos));
startActivityForResult(intent, REQUEST_CODE);
}
});
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && requestCode == REQUEST_CODE) {
String item = data.getStringExtra("item");
int itemPosition = Integer.parseInt(data.getStringExtra("itemPos"));
toDoItems.add(itemPosition, item);
toDoItems.remove(itemPosition + 1);
adapter.notifyDataSetChanged();
}
}
public void addItem(View v) {
EditText newItem = (EditText) findViewById(R.id.itemInputEditText);
if (newItem.getText().length() == 0) {
Toast.makeText(this, "You need to enter a to do.", Toast.LENGTH_SHORT).show();
} else {
String item = newItem.getText().toString();
databaseHelper.insertData(item);
adapter.add(item);
newItem.setText("");
}
}
public void getToDos(){
SQLiteDatabase database = databaseHelper.getWritableDatabase();
Cursor cursor = database.rawQuery("select * from student",null);
if (cursor.moveToFirst()) {
while (!cursor.isAfterLast()) {
String name = cursor.getString(cursor.getColumnIndex("todo"));
adapter.add(name);
adapter.notifyDataSetChanged();
cursor.moveToNext();
}
}
}
public boolean itemDeleteFromDatabase(Long id) {
SQLiteDatabase database = databaseHelper.getWritableDatabase();
boolean databaseDelete = database.delete(TABLE_NAME, TO_DO + "=?", new String[]{Long.toString(id)}) > 0;
listItems.setAdapter(adapter);
return databaseDelete;
}
}
DatabaseHelper.java
public class DatabaseHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "todo.db";
public static final String TABLE_NAME = "student";
public static final String ID = "id";
public static final String TO_DO = "todo";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, 1);
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
String CREATE_TO_DO_TABLE = "CREATE TABLE "
+ TABLE_NAME
+ "("
+ ID
+ " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ TO_DO
+ " TEXT"
+ ")";
sqLiteDatabase.execSQL(CREATE_TO_DO_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(sqLiteDatabase);
}
public boolean insertData(String todo) {
SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(TO_DO, todo);
long result = sqLiteDatabase.insert(TABLE_NAME, null, contentValues);
if (result == -1) {
return false;
} else {
return true;
}
}
public Cursor getListContents() {
SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
Cursor data = sqLiteDatabase.rawQuery("SELECT * FROM " + TABLE_NAME, null);
return data;
}
}
SQL is basically saying that you haven't provided an argument to match the placement ?. i.e.
boolean databaseDelete = database.delete(TABLE_NAME, TO_DO + "=?" + id, null) > 0;
Is effectively saying DELETE FROM table WHERE TO_DO =unobtainablevale 10
10 being a made-up id for demonstration
You could change it to
boolean databaseDelete = database.delete(TABLE_NAME, TO_DO + "=" + id, null) > 0;
or to
boolean databaseDelete = database.delete(TABLE_NAME, TO_DO + "=?", new String[]{Long.toString(id)}) > 0;
The latter probably being considered the better.
P.S. not tested so the odd typo might exist.
Solution 1 using a SimpleCursorAdapter as opposed to an ArrayAdpater
1) in DatabaseHelper change public static final String ID = "id"; to be public static final String ID = "_id"; (i.e add the underscore, suggest do this irrespective of method used but NEEDED for CursorAdapter)
Note! This will require the existing database to be deleted. Use Settings/Apps, select App and then clear data or uninstall app.
2) add the lines indicated with <<<<< to MainActivity (preparing to use Cursor Adapter, ps will leave the ArrayAdapter stuff generally asis but have to remove some)
ArrayList<String> toDoItems = new ArrayList<>();
ArrayAdapter<String> adapter;
SimpleCursorAdapter altadapter; //<<<<<<<<<
Cursor itemlistcursor; //<<<<<<<<<
ListView listItems;
3) Add override for onDestroy method (not required but cleans up cursor) :-
#Override
public void onDestroy() {
super.onDestroy();
itemlistcursor.close();
}
4) Add altertantive method e.g. getItemListAsCursor to get data:-
public void getItemListAsCursor() {
SQLiteDatabase database = databaseHelper.getWritableDatabase();
itemlistcursor = database.query(TABLE_NAME,null,null,null,null,null,null);
}
Note! uses query method instead of rawQuery but equates to SELECT * FROM student;
5) Change itemDeleteFromDatabase to use ID column not the TODO column (didn't spot this before) and comment out lines as per the code below:-
public boolean itemDeleteFromDatabase(Long id) {
SQLiteDatabase database = databaseHelper.getWritableDatabase();
boolean databaseDelete = database.delete(TABLE_NAME, ID + "=?", new String[]{Long.toString(id)}) > 0;
//listItems.setAdapter(adapter);
return databaseDelete;
}
6) Comment out the lines as below (get rid of using ArrayAdapater) :-
listItems = (ListView) findViewById(R.id.listViewItems);
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, toDoItems);
//listItems.setAdapter(adapter);
databaseHelper = new DatabaseHelper(this);
//getToDos();
7) Change onItemLongClickListener as below
listItems.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> adapter, View item, int position, long id) {
//toDoItems.remove(position);
itemDeleteFromDatabase(id); //<<<<<<
getItemListAsCursor(); //<<<<<<
//MainActivity.this.adapter.notifyDataSetChanged();
altadapter.swapCursor(itemlistcursor); //<<<<<<
return true;
}
});
Note! could keep notifyDatasetChanged (I just prefer swapCursor);
8) Finally add the following just after the commented out //getToDos line :-
getItemListAsCursor();
altadapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1,
itemlistcursor,
new String[]{ TO_DO},
new int[]{android.R.id.text1},
0);
listItems.setAdapter(altadapter);
Solution 2 using ArrayAdpater
1) Add the complimentary Array for the ID (as per the //<<<<<< line):-
ArrayList <String> toDoItems = new ArrayList<>();
ArrayList<Long> toDoItemsID = new ArrayList<>(); //<<<<<<
ArrayAdapter<String> adapter;
ListView listItems;
2) Change insertData method in DatabaseHelper to return the id by replacing the method with :-
public long insertData(String todo) {
SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(TO_DO, todo);
return sqLiteDatabase.insert(TABLE_NAME, null, contentValues);
}
3) Change getToDos method to store id into the compliementary array (//<<<<< ):-
public void getToDos(){
SQLiteDatabase database = databaseHelper.getWritableDatabase();
Cursor cursor = database.rawQuery("select * from student",null);
if (cursor.moveToFirst()) {
while (!cursor.isAfterLast()) {
String name = cursor.getString(cursor.getColumnIndex(TO_DO));
adapter.add(name);
toDoItemsID.add(cursor.getLong(cursor.getColumnIndex(ID))); //<<<<<<
adapter.notifyDataSetChanged();
cursor.moveToNext();
}
}
}
Note! I have also replaced "todo" with TO_DO
4) Change addItem method to also store id
public void addItem(View v) {
EditText newItem = (EditText) findViewById(R.id.itemInputEditText);
if (newItem.getText().length() == 0) {
Toast.makeText(this, "You need to enter a to do.", Toast.LENGTH_SHORT).show();
} else {
String item = newItem.getText().toString();
//databaseHelper.insertData(item); //OLD
toDoItemsID.add(databaseHelper.insertData(item)); //<<<<<<<
adapter.add(item);
newItem.setText("");
}
}
Note! I don't like this at all I can envisage issue with keeping toDoItemsID in sync, plus this does currently cater for a not inserted (easy to do as return from insertData should be > 0).
5) Finally the onItemLongClickListener changes :-
listItems.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> adapter, View item, int position, long id) {
itemDeleteFromDatabase(toDoItemsID.get(position)); //<<<<<<
toDoItems.remove(position);
toDoItemsID.remove(position); //<<<<<<
//itemDeleteFromDatabase(id + 1); // REMOVE
MainActivity.this.adapter.notifyDataSetChanged();
return true;
}
});
I've tested the above, but may have inadvertently missed something when copying.
Good day, I want to fetch my database data using an Adapter and display it in my RecylcerViewer. But I don't know how to implement it. Hoping that you will guide me how to accomplish these task
I want to replace these data to my database data but I don't know how to do it.
//I want to replace this dummy data to my database data
MyAdapter adapter = new MyAdapter(new String[]{"Dummy Data1", "Dummy Data2"});
AccntFragment.java
public class AccountsFragment extends Fragment {
public AccountsFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_accounts, container, false);
RecyclerView rv = (RecyclerView) rootView.findViewById(R.id.rv_recycler_view);
rv.setHasFixedSize(true);
//I want to replace this dummy data to my database data
MyAdapter adapter = new MyAdapter(new String[]{"Dummy Data1", "Dummy Data2"});
rv.setAdapter(adapter);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
return rootView;
}
}
MyAdapter.java
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private String[] mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class MyViewHolder extends RecyclerView.ViewHolder {
public CardView mCardView;
public TextView account_type;
public TextView accnt_description;
public TextView balance_label;
public TextView account_balance;
public MyViewHolder(View v) {
super(v);
mCardView = (CardView) v.findViewById(R.id.card_view);
account_type = (TextView) v.findViewById(R.id.lblShareCapital);
balance_label = (TextView) v.findViewById(R.id.lblAvailableBalance);
accnt_description = (TextView) v.findViewById(R.id.sl_desc);
account_balance = (TextView) v.findViewById(R.id.actual_balance);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(String[] myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_item, parent, false);
// set the view's size, margins, paddings and layout parameters
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
holder.account_type.setText(mDataset[position]);
holder.mCardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String currentValue = mDataset[position];
Log.d("CardView", "CardView Clicked: " + currentValue);
}
});
}
#Override
public int getItemCount() {
return mDataset.length;
}
}
SQliteHandler.java
public void addUser(String br_code, String mem_id, String username, String email, String created_at) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(BR_CODE, br_code); // branch code
values.put(MEM_ID, mem_id); // mem id
values.put(MEM_USERNAME, username); // username
values.put(MEM_EMAIL, email); // Email
values.put(MEM_CREATED_AT, created_at); // Created At
// Inserting Row
long id = db.insertOrThrow(TABLE_MEMBERS, null, values);
db.close(); // Closing database connection
Log.d(TAG, "Member's info was inserted successfully: " + id);
Log.d(TAG, "BR CODE: " + br_code);
Log.d(TAG, "Member ID: " + mem_id);
Log.d(TAG, "Username: " + username);
Log.d(TAG, "Email: " + email);
Log.d(TAG, "Created at: " + created_at);
Log.d(TAG, "---------------------------------");
}
/**
* Getting user data from database
* */
public HashMap<String, String> getUserDetails() {
HashMap<String, String> user = new HashMap<String, String>();
String selectQuery = "SELECT * FROM " + TABLE_MEMBERS;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// Move to first row
cursor.moveToFirst();
if (cursor.getCount() > 0) {
user.put("br_code", cursor.getString(0));
user.put("mem_id", cursor.getString(1));
user.put("username", cursor.getString(2));
user.put("email", cursor.getString(3));
user.put("created_at", cursor.getString(4));
Log.d(TAG, "Members's data: " + user.toString());
}
else{
Log.d(TAG, "member's data is empty");
}
cursor.close();
db.close();
// return user
Log.d(TAG, "Member's info was successfully fetch: " + user.toString());
return user;
}
/**
* Storing user SL details in database
* */
public void addUserSLDTL(String sl_desc, String tr_date, String actual_balance, String available_balance){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(SL_DESC, sl_desc); // sl desc
values.put(TR_DATE, tr_date); // trans date
values.put(ACTUAL_BALANCE, actual_balance); // actual balance
values.put(AVAILABLE_BALANCE, available_balance); // availabe balance
// Inserting Row
long id = db.insertOrThrow(TABLE_MEMBERS_SLDTL, null, values);
db.close(); // Closing database connection
Log.d(TAG, "Members's SL Details was successfully: " + id);
Log.d(TAG, "SL Desc: " + sl_desc);
Log.d(TAG, "Transaction Date: " + tr_date);
Log.d(TAG, "Actual Balance: " + actual_balance);
Log.d(TAG, "Available Balance: " + available_balance);
}
/**
* Getting user SL details data from database
* */
public HashMap<String, String> getUserSLDTL() {
HashMap<String, String> sl_summ = new HashMap<String, String>();
String selectQuery = "SELECT * FROM " + TABLE_MEMBERS_SLDTL;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// Move to first row
cursor.moveToFirst();
if (cursor.getCount() > 0) {
sl_summ.put("sl_desc", cursor.getString(0));
sl_summ.put("tr_date", cursor.getString(1));
sl_summ.put("actual_balance", cursor.getString(2));
sl_summ.put("available_balance", cursor.getString(3));
Log.d(TAG, "Member's SL Details: " + sl_summ.toString());
}
else{
Log.d(TAG, "member's SLDTL data is empty");
}
cursor.close();
db.close();
// return user
Log.d(TAG, "Member's SL Details was successfully fetch: " + sl_summ.toString());
return sl_summ;
}
I am just giving you a sample code :-
If you are using String[] then you can replace List and ArrayList into String[].
I am just writing code using List.
you should fetch list of data first.
public List<HashMap<String, String>> getUserDetails() {
HashMap<String, String> user = new HashMap<>();
List<HashMap<String,String>> userList = new ArrayList<>();
// write content values into HashMap
// And add hashMap into List
// userList.add(user);
return userList;
}
And make a method in Adapter like this to notify Adapter :-
static void setList(List<HashMap> list) {
if (list != null && list.size() > 0) {
adapterList.addAll(list);
}
notifyDataSetChanged();
}
List<HashMap<String,String>> userDetailList = getUserDetails();
Once you got data from DataBase then you can call
adapter.setList(userDetailList)
Note : all database operation should do in background thread.
Lets say you can create Members class like
You can change the data type of member variables as per your need:
public class member
{
public int brachCode;
public int mem_id;
public String username;
public String email;
public Date crated_at;
public int getBrachCode() {
return brachCode;
}
public void setBrachCode(int brachCode) {
this.brachCode = brachCode;
}
public int getMem_id() {
return mem_id;
}
public void setMem_id(int mem_id) {
this.mem_id = mem_id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getCrated_at() {
return crated_at;
}
public void setCrated_at(Date crated_at) {
this.crated_at = crated_at;
}
}
And change your SQliteHandler class method as below...
/**
* Getting user data from database
* */
public List<Member> getUserDetails() {
String selectQuery = "SELECT * FROM " + TABLE_MEMBERS;
List<Member> mMemberDetails = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// Move to first row
cursor.moveToFirst();
if (cursor.getCount() > 0) {
Member pMemebr = new Member();
pMemebr.setBrachCode(cursor.getString(0));
pMemebr.setMem(cursor.getString(1));
pMemebr.setUsername(cursor.getString(2));
pMemebr.setEmail(cursor.getString(3));
pMemebr.setCrated(cursor.getString(4));
mMemberDetails.add(pMemebr);
Log.d(TAG, "Members's data: " + user.toString());
}
else{
Log.d(TAG, "member's data is empty");
}
cursor.close();
db.close();
return mMemberDetails;
}
in your MyAdapter classs change the constructor from this...
private String[] mDataset;
to this..
private List<Member> mDataset;
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(String[] myDataset) {
mDataset = myDataset;
}
to this...
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(List<Member> mMemberDetails) {
mDataset = mMemberDetails;
}
and in onBindViewHolder() change this line :
String currentValue = mDataset[position];
Log.d("CardView", "CardView Clicked: " + currentValue);
to this...
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(List<Member> mMemberDetails) {
mDataset = mMemberDetails;
}
that's it. It will work now.
I have a listview with data using customAdapter.class now what i want is that to transfer checked items in listview to secondActivity on button click...
btest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SparseBooleanArray checked = listView.getCheckedItemPositions();
ArrayList<Model> mylist = new ArrayList<Model>();
for (int i = 0; i < checked.size(); i++) {
int position = checked.keyAt(i);
if (checked.valueAt(i))
// listView = new ArrayList<Model>();
mylist.add(String.valueOf(adapter.getItem(position)));
}
String[] output = new String[mylist.size()];
for (int i = 0; i < mylist.size(); i++) {
output[i] = (mylist.get(i));
}
Intent intent = new Intent(getApplicationContext(), ResultActivity.class);
Bundle b = new Bundle();
b.putStringArray("selectedItems", output);
// b.putStringArrayList("SelectedItems: ",list);
// b.putString("selectedItems", String.valueOf(output));
intent.putExtras(b);
startActivity(intent);*/
}
});
and this is the second activity where i am getting that data in another listview
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.result);
Bundle b = getIntent().getExtras();
String[] result = b.getStringArray("selectedItems");
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, result);
lv.setAdapter(adapter);
}
The method you followed to send custom list to another activity will not work. In order to transfer your custom list between activities you need to create Parcelable List and send it through intent.
Android Intents does not support custom list.
Custom list can be passed in two ways, Serialization and Parcelable.
But Parcelable is more Efficient and Simple to implement.
Refer this link to send custom list between activities through Parcelable
This link will give you much better idea to implement Parcelable.
Updated Code: Change your Model Code like below.
public class Model implements Parcelable{
private String name;
private int selected;
public Model(String name){
this.name = name;
selected = 0;
}
public String getName(){
return name;
}
public int isSelected(){
return selected;
}
public void setSelected(boolean selected){
this.selected = selected;
}
#Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
/**
* Storing the Student data to Parcel object
**/
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(selected);
}
private Model (Parcel in){
this.name = in.readString();
this.selected = in.readInt();
}
public static final Parcelable.Creator<Model> CREATOR = new Parcelable.Creator<Model>() {
#Override
public Student createFromParcel(Parcel source) {
return new Student(source);
}
#Override
public Model[] newArray(int size) {
return new Model[size];
}
};
}
Then in the MainActivity do this..
Intent next = new Intent(MainActivity , ResultActivity.class);
next.putParcelableArrayListExtra("model_data", (ArrayList<? extends Parcelable>) selectedItems);
startActivity(next);
In the ResultActivity do this.
ArrayList<Model> his = getIntent().getParcelableArrayListExtra("model_data");
Try the above code..
Good Luck..!!
i solve by saving checked items from listview to sqlite on button click. another button to open new activity and call selected items sqlite this way...
oncheckchange add and remove items in an arraylist and call this in onbutton click like this way...
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder view = null;
Support support = (Support) this.getItem(position);
if (convertView == null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.view_items, null);
view = new ViewHolder();
view.tvInfo = (TextView) convertView.findViewById(R.id.tvInfo);
view.cb = (CheckBox) convertView.findViewById(R.id.cb);
convertView.setTag(view);
view.cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
CheckBox cb = (CheckBox) buttonView;
Support support = (Support) cb.getTag();
support.setSelected(cb.isChecked());
if (isChecked){
selList.add(support.status);
selID.add(support.id);
selType.add(support.type);
// Toast.makeText(CustomAdapter.this, "Clicked on Checkbox: " + cb.getText() + " is " + cb.isChecked(), Toast.LENGTH_LONG).show();
}else {
selList.remove(support.status);
selID.remove(support.id);
selType.remove(support.type);
}
}
});
}else{
view = (ViewHolder) convertView.getTag();
view.cb = view.getCb();
view.tvInfo = view.getTvInfo();
}
view.cb.setTag(support);
support = list.get(position);
String id = support.getId();
String status = support.getStatus();
String type = support.getType();
view.cb.setChecked(support.isSelected());
// view.tvInfo.setText(id + "," + status + "," + type);
view.tvInfo.setText(status);
return convertView;
}
this is button coding to add to db
btest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
handler.addSelected(adapter.selList, adapter.selID, adapter.selType);
and this is how to insert to sqlite..
public void addSelected(ArrayList<String> selList, ArrayList<String> selID, ArrayList<String> selType) {
int size = selID.size();
SQLiteDatabase db = getWritableDatabase();
try{
for (int i = 0; i < size ; i++){
ContentValues cv = new ContentValues();
// cv.put(KEY_ID, selID.get(i).toString());
cv.put(KEY_ID, selID.get(i));
cv.put(KEY_STATUS, selList.get(i));
cv.put(KEY_TYPE, selType.get(i));
Log.d("Added ",""+ cv);
db.insertOrThrow(TABLE_SELECTED, null, cv);
}
db.close();
}catch (Exception e){
Log.e("Problem", e + " ");
}
}
and get back from db like this
public ArrayList<String> getSelected() {
SQLiteDatabase db = this.getReadableDatabase();
ArrayList<String> result = null;
try{
result = new ArrayList<String>();
// String query = "SELECT * FROM " + TABLE_SELECTED;
String query = "SELECT " + KEY_ID + " FROM " + TABLE_SELECTED;
Cursor c = db.rawQuery(query, null);
if (!c.isLast()){
if (c.moveToFirst()){
do{
String sel_name = c.getString(c.getColumnIndex("_id"));
result.add(sel_name);
Log.d("Added ", sel_name);
}while (c.moveToNext());
}
}
c.close();
db.close();
}catch (Exception e){
Log.e("Nothing is to show", e + " ");
}
return result;
}
I'm trying to pass the ListView position via intent and not the id. Is there anyway of doing this. When I delete an item, i want to pass the changed position. Currently, both the position and id are the same.
If there's a better way (i.e. if statement in 2nd view), please explain.
public class MyCollection extends Activity {
private ListView listView;
List<MyMovieDataModel> movieList;
MyDatabase database;
MyMovieAdapter myMovieAdapter;
private static final String TAG = "popularmovies";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_collection_main);
database = new MyDatabase(this);
movieList = database.getAllItems();
myMovieAdapter = new MyMovieAdapter(this, R.layout.my_collection_row, movieList);
listView = (ListView) findViewById(R.id.myCollection_listView);
listView.setAdapter(myMovieAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(MyCollection.this, MyDetailView.class);
intent.putExtra("movie", position);
Log.d(TAG, "Intent position: " + position);
Log.d(TAG, "Intent id: " + id);
startActivity(intent);
}
});
clickToDetail();
}
public void clickToDetail() {
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(MyCollection.this, MyDetailView.class);
intent.putExtra("movie", position);
Log.d(TAG, "Intent position: " + position);
Log.d(TAG, "Intent id: " + id);
startActivity(intent);
}
});
}
This is from 2nd view:
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
mPosition = bundle.getInt("movie");
Log.d(TAG, "Bundle mPosition: " + mPosition);
}
moviePosition = (int) (mPosition + 1);
Log.d(TAG, "Bundle moviePosition: " + moviePosition);
MyDatabase myDatabase = new MyDatabase(this);
database = myDatabase.getWritableDatabase();
String selectQuery = "SELECT * FROM " + MyDatabase.DATABASE_TABLE + " WHERE _id = " + moviePosition;
Log.d(TAG, "SQL Query Position: " + moviePosition);
Cursor cursor = database.rawQuery(selectQuery, null);
if (cursor != null && cursor.moveToFirst()) {
do {
idList.add(cursor.getInt(0));
list.add(cursor.getString(1));
list.add(cursor.getString(2));
list.add(cursor.getString(3));
list.add(cursor.getString(4));
//list.add(cursor.getString(5));
} while (cursor.moveToNext());
}
cursor.moveToFirst();
//Link & Set Detail Views//
detailID = (TextView) findViewById(R.id.detailID);
detailID.setText(cursor.getString(0));
detailTitle = (TextView) findViewById(R.id.detailTitle);
detailTitle.setText(cursor.getString(1));
detailDate = (TextView) findViewById(R.id.detailDate);
detailDate.setText(cursor.getString(2));
detailRating = (TextView) findViewById(R.id.detailRating);
detailRating.setText(cursor.getString(3));
detailSynopsis = (TextView) findViewById(R.id.detailSynopsis);
detailSynopsis.setText(cursor.getString(4));
//detailPoster = (ImageView) findViewById(R.id.detailPoster);
}
I'm guessing you are correctly passing item's position through intent; all you need to do is in your MyDetailView, call
getIntent().getIntExtra("movie", 0);
where "movie" has to be the same String value as you specified when putting extra into intent, and 0 is the default value that will be passed if there is no value associated with the key(in this case "movie"). Then you can receive correct item's position.
Hy guys!
I've got a problem. My app should display all routes in a listview. But there is something wrong with the arrayadapter. If i try my arrayadapter like this:
ArrayAdapter<DefineRoute> adapter = new ArrayAdapter<DefineRoute>(
this, android.R.layout.simple_list_item_1,verbindungen.getVerbindungen());
it works, but it only display the objectname of DefineRoute and i wanna display the output of the cursor.
Ithink i should try:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
this, android.R.layout.simple_list_item_1,verbindungen.getVerbindungen());
But here comes the error: Cannot resolve constructor ArrayAdapter
Here is my Acticity:
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated constructor stub
super.onCreate(savedInstanceState);
setContentView(R.layout.planausgabelayout);
//Aufruf der TextViews
TextView txtStart = (TextView)findViewById(R.id.txtAusgabeStart);
TextView txtZiel = (TextView)findViewById(R.id.txtAusgabeZiel);
TextView txtZeit = (TextView)findViewById(R.id.txtAusgabeZeit);
intent = getIntent();
txtStart.setText(intent.getStringExtra("StartHaltestelle"));
txtZiel.setText(intent.getStringExtra("ZielHaltestelle"));
txtZeit.setText(intent.getStringExtra("Zeit"));
getRoute();
}
public void getRoute() {
lvList = (ListView)findViewById(R.id.lvList);
Verbindungen verbindungen = new Verbindungen(this);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
this, android.R.layout.simple_list_item_1,verbindungen.getVerbindungen());
lvList.setAdapter(adapter);
}
Here is my Activity Define Route:
public class DefineRoute {
private String abfahrtszeit;
private String ankunftszeit;
private String dauer;
private String umstieg;
public DefineRoute(String abfahrtszeit, String ankunftszeit, String dauer, String umstieg)
{
this.abfahrtszeit = getAbfahrtszeit();
this.ankunftszeit = getAnkunftszeit();
this.dauer = getDauer();
this.umstieg = getUmstieg();
}
public String getAbfahrtszeit() {
return abfahrtszeit;
}
public String getAnkunftszeit() {
return ankunftszeit;
}
public String getDauer() {
return dauer;
}
public String getUmstieg() {
return umstieg;
}
}
Here is my Activity Verbindungen:
public class Verbindungen {
SQLiteDatabase db;
LinkedList<DefineRoute> route;
DefineRoute[] routeArray;
Context context;
DatabaseHelper myDbHelper = null;
public Verbindungen(Context context) {
route = new LinkedList<DefineRoute>();
this.context = context;
myDbHelper = new DatabaseHelper(context);
}
public DefineRoute[] getVerbindungen() {
try {
myDbHelper.createDataBase();
} catch (IOException ioe) {
throw new Error("Unable to create database");
}
try {
myDbHelper.openDataBase();
}catch(SQLException sqle){
throw sqle;
}
db = myDbHelper.getReadableDatabase();
// Alle Daten der Datenbank abrufen mithilfe eines Cursors
Cursor cursor = db.rawQuery("SELECT strftime('%H:%M', f.abfahrt) AS Abfahrt," +
"strftime('%H:%M', f.ankunft) AS Ankunft," +
"strftime('%H:%M', strftime('%s',f.ankunft)- strftime('%s',f.abfahrt), 'unixepoch') AS Dauer," +
"r.name AS Route," +
"count(u.fahrt_id) AS Umstiege " +
"FROM scotty_fahrt f " +
"JOIN scotty_haltestelle start ON f.start_id = start.id " +
"JOIN scotty_haltestelle ziel ON f.ziel_id = ziel.id " +
"JOIN scotty_route r ON f.route_id = r.id " +
"LEFT OUTER JOIN scotty_umstiegsstelle u ON f.id = u.fahrt_id " +
"WHERE start.name = 'Linz/Donau Hbf (Busterminal)' " +
"AND ziel.name = 'Neufelden Busterminal (Schulzentrum)' " +
"GROUP BY u.fahrt_id",null);
cursor.moveToFirst();
int i=0;
while (cursor.moveToNext()){
//in this string we get the record for each row from the column "name"
i++;
}
routeArray = new DefineRoute[i];
cursor.moveToFirst();
int k =0;
while (cursor.moveToNext())
{
routeArray[k] = new DefineRoute(cursor.getString(0),cursor.getString(1),cursor.getString(2),
cursor.getString(3));
k++;
}
//here we close the cursor because we do not longer need it
//}
cursor.close();
myDbHelper.close();
return routeArray;
}
please help me.
Now i am creating a ArrayAdapter class where i define my ouput in the listview with:
public class RouteAdapter extends ArrayAdapter<DefineRoute>{
Activity context;
DefineRoute[] defineroute;
public RouteAdapter(Activity context, DefineRoute[] defineroute){
super(context, R.layout.layoutausgabe, defineroute);
this.defineroute = defineroute;
this.context = context;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View row = inflater.inflate(R.layout.layoutausgabe,null);
TextView txZeit = (TextView)row.findViewById(R.id.txZeit);
TextView txDauer = (TextView)row.findViewById(R.id.txDauer);
TextView txUmstieg = (TextView)row.findViewById(R.id.txUmstieg);
DefineRoute defineRoute = defineroute[position];
txZeit.setText(defineRoute.getAbfahrtszeit() + " - " + defineRoute.getAnkunftszeit());
txDauer.setText(defineRoute.getDauer());
txUmstieg.setText(defineRoute.getUmstieg());
return row;
}
}
How should i continue?
and what should my adapter look like?
Your ArrayAdapter<String> is type of String so pass String list to it's constructor instead of verbindungen.getVerbindungen() list of objects.
ArrarAdapter < T > is any type of class you can use
in your case ArrayAdapter so you need override toString method of DefineRoute class
in your case
#Override
public String toString() {
return ankunftszeit+" "+ankunftszeit;
//or what ever you want to displat
}
or there is other Solution is Create your Own adapter extending by BaseAdapter Class.