My current application has a Listview which pulls and displays data from a sqlite DB. Data in the first column of the DB is displayed in the listview and when clicked, an activity starts showing the rest of the column associated with the first column. When the data is edited, the DB updates but the listview does not show the updates unless the application is restarted. I am trying to implement startActivityForResult() in my onResume method but am unsuccessful. I am trying to refresh my listview after the DB has been updated. How can I accomplish this.
ListView Activity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_listview);
loginList = (ListView)
findViewById(R.id.loginlist);
loginList.setOnItemClickListener(this);
webLogin = (Button)
findViewById(R.id.button3);
webLogin.setOnClickListener(this);
loginArrayList = new ArrayList<LoginDetails>();
loginListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, populateList());
loginList.setAdapter(loginListAdapter);
}
#Override
public void onClick (View v) {
Intent webLoginIntent = new Intent (this, LoginPlusActivity.class);
startActivity(webLoginIntent);
}
public List<String> populateList (){
List<String> webNameList = new ArrayList<String>();
dataStore openHelperClass = new dataStore (this);
SQLiteDatabase sqliteDatabase = openHelperClass.getReadableDatabase();
Cursor cursor = sqliteDatabase.query(dataStore.TABLE_NAME_INFOTABLE, null, null, null, null, null, dataStore.COLUMN_NAME_SITE, null);
startManagingCursor(cursor);
while (cursor.moveToNext()){
String sName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_SITE));
String wUrl = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_ADDRESS));
String uName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_USERNAME));
String pWord = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_PASSWORD));
String lNotes = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_NOTES));
LoginDetails lpDetails = new LoginDetails();
lpDetails.setsName(sName);
lpDetails.setwUrl(wUrl);
lpDetails.setuName(uName);
lpDetails.setpWord(pWord);
lpDetails.setlNotes(lNotes);
loginArrayList.add(lpDetails);
webNameList.add(sName);
}
sqliteDatabase.close();
return webNameList;
}
#Override
protected void onResume() {
super.onResume();
Intent i = new Intent(LoginList.this, UpdateDeleteLoginList.class);
LoginList.this.startActivityForResult(i, 1);
loginList.setAdapter(loginListAdapter);
loginListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, populateList());
loginList.setAdapter(loginListAdapter);
}
update Activity:
#Override
public void onClick(View v){
loginSitetext = sName.getText().toString();
loginAddresstext = wUrl.getText().toString();
loginUsertext = uName.getText().toString();
loginpassWordtext = pWord.getText().toString();
loginNotestext = lNotes.getText().toString();
LoginDetails loginDetails = new LoginDetails();
loginDetails.setsName(bundledWebSite);
loginDetails.setwUrl(bundledWebAddress);
loginDetails.setuName(bundledUserName);
loginDetails.setpWord(bundledPassWord);
loginDetails.setlNotes(bundledNotes);
if(v.getId()==R.id.rucBttn){
finish();
}else if(v.getId()==R.id.ruuBttn){
updateLoginDetails(loginDetails);
Intent returnIntent = new Intent();
setResult(RESULT_CANCELED, returnIntent);
finish();
}else if(v.getId()==R.id.rudBttn){
deleteLoginDetails(loginDetails);
}
}
private void updateLoginDetails(LoginDetails loginDetails){
dataStore androidOpenDbHelper = new dataStore(this);
SQLiteDatabase sqliteDatabase = androidOpenDbHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(dataStore.COLUMN_NAME_SITE, loginSitetext);
contentValues.put(dataStore.COLUMN_NAME_ADDRESS, loginAddresstext);
contentValues.put(dataStore.COLUMN_NAME_USERNAME, loginUsertext);
contentValues.put(dataStore.COLUMN_NAME_PASSWORD, loginpassWordtext);
contentValues.put(dataStore.COLUMN_NAME_NOTES, loginNotestext);
String[] whereClauseArgument = new String[1];
whereClauseArgument[0] = loginDetails.getsName();
System.out.println("whereClauseArgument[0] is :" + whereClauseArgument[0]);
sqliteDatabase.update(dataStore.TABLE_NAME_INFOTABLE, contentValues, dataStore.COLUMN_NAME_SITE+"=?", whereClauseArgument);
sqliteDatabase.close();
finish();
You can refresh the listview by calling notifyDataSetUpdated on the adapter. That forces the entire listview to refresh, and getView will be called on all views refreshing it.
The problem you're asking about has a standard solution, that is (unfortunately) more complex than a few lines of code. It is accomplished by a combination of Content Provider, Data Loader and Cursor Adapter.
I've put a little demo on GitHub that has a skeleton containing all the components and can be modified to accomplish what you need. It also handles one-pane / two-pane layouts on tablets (and newer phones as well).
Content provider is the module that serves as an interface to your database table and notifies your ListView about the changes, thus taking care of immediate refreshing of the list. Just grep for 'getContentResolver().notifyChange()' calls, these take care of refreshing your list. As long as you use Content Provider for all access to your data (CRUD - query,insert,delete,update,...), all your actions will be immediately reflected in the ListView.
There is a lot of info about this by Wolfram Rittmeyer, Lars Vogel, Alex Lockwood, ... if you want to get educated about the problem.
Good Luck
Related
When item of listview is clicked, it gets opened in another activity which has edittext. After editing an item, when I save it, item does not get updated in the listview but it inserts a new entry in listview.
How can I update existing item without inserting new?
Here is my code
Activity: TRList.class
ArrayList<HashMap<String, String>> items = new ArrayList<>();
List<TRListFormat> list = trDb.getAllReminders();
for (TRListFormat val : list) {
HashMap<String, String> map = new HashMap<>();
map.put("title",val.getTitle());
map.put("description", val.getDes());
map.put("date", val.getDate());
map.put("time", val.getTime());
items.add(map);
}
adapter = new SimpleAdapter(this, items, R.layout.tr_list_format,
new String[] { "title", "description", "date", "time" },
new int[] {R.id.tbr_title, R.id.tbr_des, R.id.tbr_date, R.id.tbr_time });
lv = (ListView)findViewById(R.id.tbr_list);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
Intent intent = new Intent(TRList.this, TRTimeReminder.class);
intent.putExtra("remId", (int)id);
startActivity(intent);
}
});
When listView item is clicked, it opens another activity
TRTimeReminder.class I have set save button in menu
case R.id.menu_tbr_done:
String title = edTitle.getText().toString();
String des = edDes.getText().toString();
String time = timeView.getText().toString();
String date = dateView.getText().toString();
Bundle extras = getIntent().getExtras();
if(extras != null) {
int value = extras.getInt("remId");
if (value > 0) {
trDb.updateReminder(new TRListFormat(value, title, des, date, time));
}
}
else{
trDb.addReminder(new TRListFormat(title, des, date, time));
}
Intent i = new Intent(getApplicationContext(), TRList.class);
startActivity(i);
edTitle.getText().clear();
edDes.getText().clear();
dateView.setText(currDate);
timeView.setText(currTime);
return true;
TRDBHelper.class
//Add new reminder
void addReminder(TRListFormat format){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COLUMN_TITLE, format.getTitle());
values.put(COLUMN_DES, format.getDes());
values.put(COLUMN_DATE, format.getDate());
values.put(COLUMN_TIME, format.getTime());
db.insert(TABLE_NAME, null, values);
db.close();
}
//Update single reminder
public void updateReminder(TRListFormat format){
SQLiteDatabase db = this.getWritableDatabase();
int id = format.getId();
ContentValues values = new ContentValues();
values.put(COLUMN_ID, format.getId());
values.put(COLUMN_TITLE, format.getTitle());
values.put(COLUMN_DES, format.getDes());
values.put(COLUMN_DATE, format.getDate());
values.put(COLUMN_TIME, format.getTime());
db.update(TABLE_NAME, values, COLUMN_ID+ " = " +id, null);
db.close();
}
I think there's problem with your adapter. There are 2 possible issues.
Data of adapter are not updated. You're saying opposite, new value is added to ListView. Are you really sure?
You haven't called your adapter's method notifyDataSetChanged() after you've changed values.
Thanks for your time in advance. I'm new to android and I'd like to learn more. I have a code that is displaying data from sql only after search is clicked and I don't know how can I make it display all the data from sql with let's say alfabetical order at first and later on if search is used it will display data matching to search request.
public class EmployeeList extends ListActivity {
protected EditText searchText;
protected SQLiteDatabase db;
protected Cursor cursor;
protected ListAdapter adapter;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
searchText = (EditText) findViewById(R.id.searchText);
db = (new DatabaseHelper(this)).getWritableDatabase();
}
public void onListItemClick(ListView parent, View view, int position, long id) {
Intent intent = new Intent(this, EmployeeDetails.class);
Cursor cursor = (Cursor) adapter.getItem(position);
intent.putExtra("EMPLOYEE_ID", cursor.getInt(cursor.getColumnIndex("_id")));
startActivity(intent);
}
public void search(View view) {
// || is the concatenation operation in SQLite
cursor = db.rawQuery("SELECT _id, firstName, lastName, title FROM employee WHERE firstName || ' ' || lastName LIKE ?",
new String[]{"%" + searchText.getText().toString() + "%"});
adapter = new SimpleCursorAdapter(
this,
R.layout.employee_list_item,
cursor,
new String[] {"firstName", "lastName", "title"},
new int[] {R.id.firstName, R.id.lastName, R.id.title});
setListAdapter(adapter);
}
}
Thanks.
i see you are using onClick in XML layout , right?
any ways, no problem.
add new method populateList() as following
public void populateList(boolean useWhere) {
// || is the concatenation operation in SQLite
if(useWhere){
cursor = db.rawQuery("SELECT _id, firstName, lastName, title FROM employee WHERE firstName || ' ' || lastName LIKE ?", new String[]{"%" + searchText.getText().toString() + "%"});
}else{
cursor = db.rawQuery("SELECT _id, firstName, lastName, title FROM employee");
}
adapter = new SimpleCursorAdapter(
this,
R.layout.employee_list_item,
cursor,
new String[] {"firstName", "lastName", "title"},
new int[] {R.id.firstName, R.id.lastName, R.id.title});
setListAdapter(adapter);
}
change search() as following:
public void search(View view){
populateList(true);
}
add a call populateList(false); to onCreate() of the activity.
so oncreate activity, will call search to execuste without WHERE and when c alled from button click, it will execute the WHERE sql
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
searchText = (EditText) findViewById(R.id.searchText);
db = (new DatabaseHelper(this)).getWritableDatabase();
populateList(false);
}
I would like to add Task name from pop up and It automatically will add to list. So, is there any way to update database automatically. Here is my method
SampleDB = this.openOrCreateDatabase("SampleDB", SQLiteDatabase.CREATE_IF_NECESSARY, null);
String query = "select *from TaskList";
Cursor c = SampleDB.rawQuery(query, null);
c.moveToFirst();
do{
String Task = c.getString(c.getColumnIndex("task"));
/* Add current Entry to results. */
results.add(Item);
}while(c.moveToNext());
this.setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, results));
This method can add items to your database:
public void addTaskToDb(SQLiteDatabase database, String task) {
ContentValues values = new ContentValues();
values.put("task", task);
database.insert("TaskList", null, values);
}
And then replace your code like this:
SampleDB = this.openOrCreateDatabase("SampleDB", SQLiteDatabase.CREATE_IF_NECESSARY, null);
ArrayAdapter<String> adapter = (ArrayAdapter<String>)this.getListAdapter();
this.addTaskToDb(SampleDB, Item);
adapter.add(Item);
I was trying to display my data dynamically in a listview. I first insert data into db then displaying them in listview. I don't understand why but I created db and listview, it doesn't show data when I try to display it.
I'm getting data from EditText fields but I insert and display the data in another activity. I first thought I coludn't get the data from first activity, but I'm sure that I wrote the right code.
The field for the data in listview always empty. I should create a new entry when I press a "Add" button. I can see that it creates a new row in the list with a new id but the rest is empty.
Why I don't see data there? This is how I get data and put inside db and list:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
String name = "";
String email = "";
String phone = "";
String address = "";
Bundle extras = getIntent().getExtras();
if (extras != null) {
name = extras.getString("name");
email = extras.getString("email");
phone = extras.getString("phone");
address = extras.getString("address");
}
listContent = (ListView)findViewById(R.id.contentlist);
mySQLiteAdapter = new SQLiteAdapter(this);
mySQLiteAdapter.openToWrite();
cursor = mySQLiteAdapter.queueAll();
String[] from = new String[]{SQLiteAdapter.KEY_ID, SQLiteAdapter.COLUMN_NAME, SQLiteAdapter.COLUMN_EMAIL,SQLiteAdapter.COLUMN_PHONE, SQLiteAdapter.COLUMN_ADDRESS};
int[] to = new int[]{R.id.id, R.id.text1, R.id.text2,R.id.text3, R.id.text4};
cursorAdapter = new SimpleCursorAdapter(this, R.layout.row, cursor, from, to);
listContent.setAdapter(cursorAdapter);
mySQLiteAdapter.insert(name,email,phone,address);
updateList();
}
This is my main activity
Button next = (Button) findViewById(R.id.add);
EditText nametext = (EditText) this.findViewById(R.id.NameText);
final String nt = nametext.getText().toString();
EditText emailtext = (EditText) this.findViewById(R.id.MailText);
final String et = emailtext.getText().toString();
EditText phonetext = (EditText) this.findViewById(R.id.PhoneText);
final String pt = phonetext.getText().toString();
EditText addresstext = (EditText) this.findViewById(R.id.AddressText);
final String at = addresstext.getText().toString();
next.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent myIntent = new Intent(getApplicationContext(), Activity2.class);
myIntent.putExtra("name",nt);
myIntent.putExtra("email",et);
myIntent.putExtra("phone",pt);
myIntent.putExtra("address",at);
startActivity(myIntent);
}
});
Here is my queueAll function:
public Cursor queueAll(){
String[] columns = new String[]{KEY_ID, COLUMN_NAME,
COLUMN_EMAIL,COLUMN_PHONE,COLUMN_ADDRESS};
Cursor cursor = sqLiteDatabase.query(MYDATABASE_TABLE, columns,
null, null, null, null, null);
return cursor;
}
I have a listview that when clicked opens up but doesnt display detailed information about that list view item. The data for the listview is entered in by a class into a sqlite datase and pulled from a sqlite database by another class. Not sure where I went wrong with the class the should pul the data when a list viewitem is clicked. I do not have enough pont to post imaged of the related xml files but the onClick methods are below
Listview:
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
Toast.makeText(getApplicationContext(), "clicked on :" + arg2, Toast.LENGTH_SHORT).show();
Intent updateDeleteLoginInfo = new Intent (this, UpdateDeleteLoginList.class);
LoginDetails clickedObject = loginArrayList.get(arg2);
Bundle loginBundle = new Bundle();
loginBundle.putString("clickedwebSite",clickedObject.getsName());
loginBundle.putString("clickedwebAddress",clickedObject.getwUrl());
loginBundle.putString("clickeduserName",clickedObject.getuName());
loginBundle.putString("clickedpassWord",clickedObject.getpWord());
updateDeleteLoginInfo.putExtras(loginBundle);
startActivity(updateDeleteLoginInfo);
Update Class:
#Override
public void onClick(View v){
loginSitetext = sName.getText().toString();
loginAddresstext = wUrl.getText().toString();
loginUsertext = uName.getText().toString();
loginpassWordtext = pWord.getText().toString();
LoginDetails loginDetails = new LoginDetails();
loginDetails.setsName(bundledWebSite);
loginDetails.setwUrl(bundledWebAddress);
loginDetails.setuName(bundledUserName);
loginDetails.setpWord(bundledPassWord);
if(v.getId()==R.id.rucBttn){
finish();
}else if(v.getId()==R.id.ruuBttn){
updateLoginDetails(loginDetails);
}else if(v.getId()==R.id.rudBttn){
deleteLoginDetails(loginDetails);
}
}
private void updateLoginDetails(LoginDetails loginDetails){
dataStore androidOpenDbHelper = new dataStore(this);
SQLiteDatabase sqliteDatabase = androidOpenDbHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(dataStore.COLUMN_NAME_SITE, loginSitetext);
contentValues.put(dataStore.COLUMN_NAME_ADDRESS, loginAddresstext);
contentValues.put(dataStore.COLUMN_NAME_USERNAME, loginUsertext);
contentValues.put(dataStore.COLUMN_NAME_PASSWORD, loginpassWordtext);
String[] whereClauseArgument = new String[1];
whereClauseArgument[0]= loginDetails.getsName();
System.out.println("whereClauseArgument[0] is :" + whereClauseArgument[0]);
sqliteDatabase.update(dataStore.TABLE_NAME_INFOTABLE, contentValues, dataStore.COLUMN_NAME_SITE+"=?", whereClauseArgument);
sqliteDatabase.close();
finish();
}
private void deleteLoginDetails(LoginDetails deleteLoginDetails){
dataStore androidOpenDbHelper = new dataStore(this);
SQLiteDatabase sqliteDatabase = androidOpenDbHelper.getWritableDatabase();
String[] whereClauseArgument = new String[1];
whereClauseArgument[0] = deleteLoginDetails.getsName();
sqliteDatabase.delete(dataStore.TABLE_NAME_INFOTABLE,dataStore.COLUMN_NAME_SITE+"=?", whereClauseArgument);
sqliteDatabase.close();
finish();
you can use notifyDataSetChanged() function to achive updating the listView.
or
assign a new adapter evrytime you update list that needs updating.
Found the 'C' in whereClauseArgument in another class was not capatalized. After capitalizing it every thing worked as it should.