Android Studio - New Item in List is not shown - java

In my App i have a ListView, if i add some new Items, the ListView does not shown the Items. The items will be shown if i close the app and go back in it.
So my new Items are saved in my Database, but the list will not be synchronized.
i followed a Tutorial on youtube, if he tries it, it works fine, but not in my app. i hope someone can help me to find my problem.
In my newItem_Activity i have an Add-Button with following Code:
btnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(todo.getName() == null){
Toast.makeText(ToDoCreateNew.this, "Please insert some value.", Toast.LENGTH_LONG).show();
return;
}
ToDoDatabaseHelper.getInstance(ToDoCreateNew.this).createTodo(todo);
finish();
}
});
My Database looks like this:
public ToDo createTodo(final ToDo todo) {
SQLiteDatabase database = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(NAME_COLUMN, todo.getName());
contentValues.put(DUEDATE_COLUMN, todo.getDueDate() == null ? null : todo.getDueDate().getTimeInMillis() / 1000);
contentValues.put(FAVORITE_COLUMN, todo.isFavorite() ? 1 : 0);
contentValues.put(DESCRIPTION_COLUMN, todo.getDescription());
contentValues.put(DUETIME_COLUMN, String.valueOf(todo.getDueTime() == null ? null : todo.getDueTime().getTime()));
long newID = database.insert(TABLE_NAME, null, contentValues);
database.close();
return readToDo(newID);
}
public List<ToDo> readAllToDos(){
List<ToDo> todos = new ArrayList<>();
SQLiteDatabase database = this.getReadableDatabase();
Cursor c = database.rawQuery("SELECT * FROM " + TABLE_NAME, null);
if (c.moveToFirst()){
do {
ToDo todo = readToDo(c.getLong(c.getColumnIndex(ID_COLUMN)));
if (todo != null){
todos.add(todo);
}
} while (c.moveToNext());
}
database.close();
return todos;
}
and this Code is on my Activity with my ListView:
List<ToDo> dataSource;
ToDoOverviewListAdapter adapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_to_do_overview);
lv = (ListView) findViewById(R.id.listToDo);
dataSource = ToDoDatabaseHelper.getInstance(this).readAllToDos();
adapter = new ToDoOverviewListAdapter(this, dataSource);
lv.setAdapter(new ToDoOverviewListAdapter(this, dataSource));
}
// Go to Activity to Add new Item - Add Button is in newItem_Activity
public void createToDo(){
startActivity(new Intent(ToDoOverview.this, ToDoCreateNew.class));
refreshListView();
}
private void refreshListView(){
dataSource.clear();
dataSource.addAll(ToDoDatabaseHelper.getInstance(this).readAllToDos());
adapter.notifyDataSetChanged();
}

Do one thing when you add lists in adapter , wrap it in a method and call that method in both onCreate and OnStart Method . So basically you have to add list in adapter two times On OnCreate method and OnStart method. So When you update the data and move back to your original activity it will trigger OnStart method and it will show updated data.

Related

is SQLiteDatabase syncronous or async?

I have an app that opens a new intent. The new intent inserts some rows on the datadabase, then finish(); it and come back to the first screen where the data should have refreshed with the new row. The code I have do not work on execution but works when debuging... so maybe there is some lag somewhere... maybe? how to wait for the query to finish?
Here is my code:
on the first screen:
setting the adapter and onResume
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
v= inflater.inflate(R.layout.filters_fragment,container,false);
createFragmentWidgets();
myrecyclerview = (RecyclerView) v.findViewById(R.id.contact_recycleview);
recyclerAdapter = new RecyclerViewAdapterFilters(getContext(), lstFilters);
myrecyclerview.setLayoutManager(new LinearLayoutManager((getActivity())));
myrecyclerview.addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL));
myrecyclerview.setAdapter(recyclerAdapter);
return v;
}
#Override
public void onResume()
{
// After a pause OR at startup
super.onResume();
lstFilters = mydb.getAllFilters("BL");
recyclerAdapter.notifyDataSetChanged();
}
the getAllFilters method on the DB class
public List<Filter> getAllFilters(String type) {
List<Filter> lstFilter = new ArrayList<>();
//hp = new HashMap();
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery( "select * from " + FILTERS_TABLE_NAME+" where type='"+type+"'", null );
res.moveToFirst();
while(res.isAfterLast() == false){
lstFilter.add(new Filter (res.getInt(res.getColumnIndex(FILTERS_COLUMN_ID)),
res.getString(res.getColumnIndex(FILTERS_COLUMN_NAME)),
res.getString(res.getColumnIndex(FILTERS_COLUMN_NUMBER)),
res.getString(res.getColumnIndex(FILTERS_COLUMN_PHOTO)),
res.getString(res.getColumnIndex(FILTERS_COLUMN_TYPE))));
res.moveToNext();
}
res.close();
db.close();
return lstFilter;
}
any ideas?
After you refresh your list, it should be enough to call notifyDataSetChanged(), however, I usually just reset the adapter:
adapter = new ClaimListAdapter(this, thisContext, claimItems);
mClaimList.setAdapter(adapter);
since you're replacing the contents of the list, call adapter.notifyDataSetChanged() to refresh the entire list.

I cant delete some rows by id in SQLite

I always cant delete first two sometimes three records. They are on Listview, when you press element you will see delete button on another layout. On Log im getting correct index for every element.
So here is my code:
Main Activity:
viewOfT.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent i=new Intent(MainActivity.this, popupWindow.class);
i.putExtra("index",id);
startActivity(i);
}
});
}
public void populateListView() {
Cursor data = db.getData();
ArrayList<String> listData = new ArrayList<>();
while(data.moveToNext()){
k.setId(data.getInt(0));
k.setTask(data.getString(1));
listData.add("- " + k.getTask());
}
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
this,
android.R.layout.simple_list_item_1,
listData);
viewOfT.setAdapter(arrayAdapter);
arrayAdapter.notifyDataSetChanged();
viewOfT.invalidateViews();
Delete button in other activity:
del.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
Bundle bundle=getIntent().getExtras();
long value=bundle.getLong("index");
db.deleteRecord(value);
finish(); }
});
And SQLHelper:
public void deleteRecord(long id) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_NAME, KEY_ID + "=" + id, null);
close();
}
1) Delete populateListView method
2) Add the following as class variables:-
SimpleCursorAdpater sca;
Cursor data;
3) in the onCreate method add :-
data = getData();
sca = new SimpleCursorAdapter(
this, // Context same as for array adapter
android.R.layout.simple_list_item_1, // layout to be used
data, // <<<<<<<< the cursor to be used for the list
new String[]{"columnname_to_be_displayed"}, // <<<<<<<< cursor column to display name
new int[android.R.id.text1], // the view into which the cursor data will be placed
0 // a flag 0 is fine
);
viewOfT.setAdapter(arrayAdapter);
4) Add a new method to override the 'onResume' method (or alter it if already overridden) :-
#Override
protected void onResume() {
super.onResume();
data = getData();
sca.swapCursor(); // can you sca.notifyDatasetChanged()
}
As you are calling another activity to delete the task, onResume will be called when returning from the other activity so the data is again retrieved from the database (deleted row will not exist) and the adpater is told to refresh the data.
You should ideally also override the onDestroy() method to close the cursor (data.close();)
Important Consideration
A cursor column named _id must exist for CursorAdapters (that's how the SimpleCursorAdapter knows what pass to the onItemClickListener).
if KEY_ID does not equate to _id; you either need to change KEY_ID to _id or amend the getData() method to include the _id column (which should be the value of the row's identifier) e.g. assuming a very basic query:
public Cursor getData() {
return db.query(TABLE_NAME,"rowid AS _id, *",null,null,null,null,null);
} // Note! will add an extra column so beware if using column offsets
or perhaps :-
public Cursor getData() {
return db.query(TABLE_NAME,KEY_ID + " AS _id, *",null,null,null,null,null);
} // Note! will add an extra column so beware if using column offsets
A Note on Column offsets
In your code you have :-
k.setId(data.getInt(0));
k.setTask(data.getString(1));
0 and 1 are column offsets (and could change e.g. the two alternative getData() methods). As such it's generally better to take advantage of the Cursor method getColumnIndex(columnname) e.g. the above could be :-
k.setId(data.getInt(data.getColumnIndex(KEY_ID));
k.setTask(data.getString(data.getColumnIndex("TASK_COLUMN")));
Note! not that you will need to create an Array as the SimpleCursorAdpater takes the cursor as the source. (KEY_ID would likely have to be prefixed with the DatabaseHelper Class).

Change SQL query based on button action

I have a listview that displays all the items in my database. I am trying to create a button that will change the data displayed to only show items that match today's date.
What is the best way to change the query that is being run in the app based on a button push and update the listview?
I've played with setting a flag in the onclick() method paired with if-else statements that held the query call, but it did not seem to switch which was being called.
The flag is the boolean filterToday. set in the onClickListener of todayButton.
public class MainActivity extends AppCompatActivity {
public final static String KEY_EXTRA_CONTACT_ID = "KEY_EXTRA_CONTACT_ID";
private ListView listView;
DBHelper dbHelper;
boolean filterToday;
Cursor cursor;
String [] columns;
int [] widgets;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button addButton = (Button) findViewById(R.id.addNew);
addButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, AddTaskActivity.class);
intent.putExtra(KEY_EXTRA_CONTACT_ID, 0);
startActivity(intent);
}
});
Button todayButton = (Button) findViewById(R.id.today);
todayButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
filterToday = true;
}
});
dbHelper = new DBHelper(this);
if(filterToday == true){
Calendar cal = Calendar.getInstance();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String date = df.format(cal.getTime());
Toast.makeText(this,date,Toast.LENGTH_LONG).show();
cursor = dbHelper.getTodaysTasks(date);
}
else{
cursor = dbHelper.getAllTasks();
}
columns = new String[] {
DBHelper.TASK_COLUMN_NAME,
DBHelper.TASK_COLUMN_TYPE,
DBHelper.TASK_COLUMN_DATE
};
widgets = new int[] {
R.id.taskName,
R.id.taskType,
R.id.taskDate
};
SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter(this, R.layout.task_info,
cursor, columns, widgets, 0);
listView = (ListView)findViewById(R.id.listView1);
listView.setAdapter(cursorAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView, View view,
int position, long id) {
Cursor itemCursor = (Cursor) MainActivity.this.listView.getItemAtPosition(position);
int taskID = itemCursor.getInt(itemCursor.getColumnIndex(DBHelper.TASK_COLUMN_ID));
Intent intent = new Intent(getApplicationContext(), AddTaskActivity.class);
intent.putExtra(KEY_EXTRA_CONTACT_ID, taskID);
startActivity(intent);
}
});
}
}
These are the two queries I am trying to switch between:
public Cursor getAllTasks() {
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery( "SELECT * FROM " + TASK_TABLE_NAME, null );
return res;
}
public Cursor getTodaysTasks(String date){
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery("SELECT * FROM " + TASK_TABLE_NAME + " WHERE " +
TASK_COLUMN_DATE + " =?", new String[]{date});
return res;
}
OK so the first thing to notice is that your update filterToday = true; inside the onclick listener, the if(filterToday == true){...} outside doesn't know that. That part is only executed once in the oncreate()
If you'd like to perform that action I suggest a small change.. like below
Create a seperate function outside for the data loading
private void LoadMyData() {
if(filterToday == true){
Calendar cal = Calendar.getInstance();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String date = df.format(cal.getTime());
//you might need to update this line
//Toast.makeText(this,date,Toast.LENGTH_LONG).show();
//assume dbHelper is ready at this point
cursor = dbHelper.getTodaysTasks(date);
}
else{
cursor = dbHelper.getAllTasks();
}
}
Call this function inside onclick listner
filterToday = false;//initialize to false if necessary
todayButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
filterToday = !filterToday ;//by doing it like this you can switch back and forth. add/check extra logic if necessary
LoadMyData();
}
});
LoadMyData(); //Call this outside in the oncreate to load the data initially
I'm not suggesting a code improvement here. Just changes to what you already have. Hope it helps.
There were two issues that I ran into, the first was comparing a string to to the SQL string[], which meant while the comparison was working, it did not behave as I expected. Once fixing this issue was updating the ListView object. This was handled by creating a new adapter and attaching it to ListView, which then updates itself.
Per this answer: Refresh Current Fragment (ListView Data) remaining in the same activity
The other option was to call notifyDataSetChanged() on the adapter, but this did not work well with the way I had my program set up.

notifyDataSetChanged() not working in ListFragment

I have a ListView in a ListFragment that is populated via a database query. It loads all the data just fine when it first populates the list in onCreate(). But when I requery the database, assign the return value to assignmentsCursor, and call notifyDataSetChanged(), it doesn't update adapter.mCursor. If I go into the Debugging mode in Eclipse I can see that assignmentsCursor.mCount has changed, but when I look at adapter.mCursor.mCount, it's the same as before. (Yes, I'm checking after notifyDataSetChanged() has been called.)
The relevant parts of my code:
SimpleCursorAdapter adapter;
Cursor assignmentsCursor;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
course = savedInstanceState.getShort(Values.ASSIGNMENT_KEY_COURSE);
}
setRetainInstance(true);
// Create and array to specify the fields we want
String[] from = new String[] { Values.KEY_TITLE, Values.ASSIGNMENT_KEY_COURSE };
// and an array of the fields we want to bind in the view
int[] to = new int[] { R.id.assignment_list_title, R.id.assignment_list_course };
// Need to give assignmentsCursor a value -- null will make it not work
updateAdapter();
adapter = new SimpleCursorAdapter(context, R.layout.assignment_list_item, assignmentsCursor, from, to);
setListAdapter(adapter);
}
public void onResume() {
super.onResume();
updateAdapter();
refresh();
}
/**
* Updates the content in the adapter.
*/
public void updateAdapter() {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean showingCompleted = sharedPrefs.getBoolean(Values.ASSIGNMENT_KEY_SHOWING_COMPLETED, false);
if (course < 0) // Showing assignments from all courses
if (showingCompleted)
assignmentsCursor = DbUtils.fetchAllAssignments(context, Values.ASSIGNMENT_LIST_FETCH, null, true);
else
assignmentsCursor = DbUtils.fetchIncompleteAssignments(context, Values.ASSIGNMENT_LIST_FETCH, null, true);
else // Showing assignments from specified course
if (showingCompleted)
assignmentsCursor = DbUtils.fetchAllAssignments(context, Values.ASSIGNMENT_LIST_FETCH, course, true);
else
assignmentsCursor = DbUtils.fetchIncompleteAssignments(context, Values.ASSIGNMENT_LIST_FETCH, course, true);
}
private void refresh() {
updateAdapter();
adapter.notifyDataSetChanged();
}
Help me!! ;)
P.S. If you need any more details/code, just let me know. I am positive that the database is querying correctly though.
Thanks to Deucalion, I have determined that I incorrectly assumed that the adapter was referencing the assignmentsCursor variable as opposed to creating a copy of the Cursor for itself. What I needed to do was just call adapter.changeCursor(assignmentsCursor) so that it updated its local copy. Thanks again Deucalion!

getting next value in android using SQLite

I have doing small application in android.During this application, i have suffer this problem:
I search the keyword using "oh" then i listing in to listview using this code.
nameList.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
try {
Intent intent = new Intent(Search.this,
SearchDetails.class);
/*
* Cursor cursor = (Cursor) adapter.getItem(position);
* intent.putExtra("JOK_ID",
* cursor.getInt(cursor.getColumnIndex("_id")));
*/
intent.putExtra("id", id);
intent.putExtra("position", position);
Log.d(TAG, " I.." + id);
Log.d(TAG, " P.." + position);
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
for example like this
Now, if I click oham then display just like this:
Finally, I want to , If i click previous button then display john and Next to display krackohm. And count total number of searched names.
I have try this code for next button:
Cursor cursor = db.rawQuery("SELECT _id, name FROM std WHERE _id = ?",
new String[]{""+Id});
if (cursor.getCount() == 1)
{
cursor.moveToFirst();
...body
}
Edit:
This is first time when any list item click, on create
private void dislpayFirstName() { // this is display first time click list item
writeDatabase();
cursor = db.rawQuery("SELECT _id, name FROM std WHERE._id = ?",
new String[]{""+Id});
if (cursor.getCount()> 0)
{
cursor.moveToFirst();
nameDetails();
}
}
This is the code for Next Button click:
position++;
writeDatabase();
cursor = db.rawQuery("SELECT _id,name FROM std", null);
if (cursor.getCount()> 0)
{
cursor.moveToPosition(position);
//cursor.moveToNext();
nameDetails();
}
In next button: If cursor.moveToPosition(position); then next name display matching position and table id. Means postion 2 then display 2 number name from table.
In next button: If cursor.moveToNext(); then next name display beginning of table.Means 0 id name from table.
You have to do it like this:
Cursor cursor = db.rawQuery("SELECT _id, name FROM std") // get all rows
Than, to display you first entry:
cursor.moveToFirst();
displayData(); // Method to display the data from the cursor on screen
Clicking you "next" Button:
if (cursor.moveToNext()){ // moveToNext returns true if there is a next row
displayData();}
And equally: with your "previous"Button use cursor.moveToPrevious()
Put cursor.moveToFirst(); at first. I mean put it like this..
cursor.moveToFirst();
if(your condition)
{
}
Instead of using id as extra with intent,you should use the position of the item in list.
The position will be similar to the position of the same record in your cursor so you just need to move your cursor to that position and fetch the detail you need from the same.Then you can display it on activity,as you have shown on your second activity view.
so in your SearchDetails.class,you need to do:
...
int position=getIntent.getIntExtra("position",999); // 999 is default value
Cursor cursor = db.rawQuery(<query which you fired for populating search results in previous activity>);
if (cursor.getCount()> 0 && position!=999){
cursor.moveToPosition(position);
...body // fetch details and display it.
}
backButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
position--;
//display details code
Cursor cursor = db.rawQuery(<query which you fired for populating search results in previous activity>);
if (cursor.getCount()> 0 && position!=-1){
cursor.moveToPosition(position);
...body // fetch details and display it.
}
}
}
nextButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
position++;
//display details code
Cursor cursor = db.rawQuery(<query which you fired for populating search results in previous activity>);
if (cursor.getCount()> 0 && position!=cursor.getCount()){
cursor.moveToPosition(position)
...body // fetch details and display it.
}
}
}
...
EDIT :
Revised code: ( repeated code removed)
...
int position=getIntent.getIntExtra("position",999); // 999 is default value
Cursor cursor = db.rawQuery(<query which you fired for populating search results in previous activity>);
if (cursor.getCount()> 0 && position!=999){
cursor.moveToPosition(position);
...body // fetch details and display it.
}
backButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
position--;
if (position!=-1){
cursor.moveToPosition(position);
...body // fetch details and display it.
}
}
nextButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
position++;
if (position!=cursor.getCount()){
cursor.moveToPosition(position)
...body // fetch details and display it.
}
}
}
...

Categories

Resources