delete item from listfragment is not working properly - android

Im doing a basic android app to learn about sqlite. The app just have a listfragment that list some products and the price like:
Pencil 1
Pen 1.20
...
And its possible to click in a item of the list to delete it. Im using cursorloader so the db operations are done in background. But Im getting a issue:
When the user clicks in a item the item is not removed from the list, but if I close and open again the app all items of the list have been removed.
Do you know where is the issue? Why the fragmentlist is not updated by removing the clicked item after click in the item and why all items are being removed?
// to list the products and the respective price
public class ProductsFragment extends ListFragment implements OnClickListener, LoaderManager.LoaderCallbacks<Cursor> {
private static final String[] PROJECTION=new String[] {
Provider.Products._ID, Provider.Products.TITLE,
Provider.Products.PRICE };
private CursorAdapter cursorAdapter;
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Cursor cursor = getActivity().getContentResolver().query(Provider.Products.CONTENT_URI, DBHelper.ALL_COLUMNS,
null,null,null,null);
String[] from = {DBHelper.TITLE, DBHelper.PRICE};
int[] to = {R.id.title, R.id.price};
cursorAdapter = new SimpleCursorAdapter(getActivity(), R.layout.item, null, from, to, 0);
setListAdapter(cursorAdapter);
getLoaderManager().initLoader(0, null, this);
}
// to delete a product
#Override
public void onListItemClick(ListView l, View v, int pos, long id) {
super.onListItemClick(l, v, pos, id);
getActivity().getContentResolver().delete(Provider.Products.CONTENT_URI,String.valueOf(id), null);
Toast.makeText(getActivity(), "Item " + id + " clicked", Toast.LENGTH_SHORT).show();
}
// cursorloader methods
#Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
return new CursorLoader(getActivity().getApplicationContext(), Provider.Products.CONTENT_URI, null, null, null, null);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
cursorAdapter.swapCursor(cursor);
}
public void onLoaderReset(Loader<Cursor> loader) {
cursorAdapter.swapCursor(null);
}
// Provider class delete method:
#Override
public int delete(Uri url, String where, String[] whereArgs) {
return database.delete(DBHelper.TABLE_PRODUCTS, where, whereArgs);
}
same issue with:
#Override
public int delete(Uri url, String where, String[] whereArgs) {
int count=db.getWritableDatabase().delete(TABLE, where, whereArgs);
getContext().getContentResolver().notifyChange(url, null);
return(count);
}
item.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
/>
<TextView
android:id="#+id/price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
/>
</RelativeLayout>
Full ProductsFragment:
public class ConstantsFragment extends ListFragment implements OnClickListener, LoaderManager.LoaderCallbacks<Cursor> {
private CursorAdapter cursorAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Cursor cursor = getActivity().getContentResolver().query(Provider.Constants.CONTENT_URI, DatabaseHelper.ALL_COLUMNS,
null,null,null,null);
String[] from = {DatabaseHelper.TITLE, DatabaseHelper.VALUE};
int[] to = {R.id.title, R.id.value};
cursorAdapter = new SimpleCursorAdapter(getActivity(), R.layout.row, null, from, to, 0);
setListAdapter(cursorAdapter);
getLoaderManager().initLoader(0, null, this);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.actions, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId()==R.id.add) {
add();
return(true);
}
return(super.onOptionsItemSelected(item));
}
#Override
public void onClick(DialogInterface dialog, int which) {
ContentValues values=new ContentValues();
AlertDialog dlg=(AlertDialog)dialog;
EditText title=(EditText)dlg.findViewById(R.id.title);
EditText value=(EditText)dlg.findViewById(R.id.value);
values.put(DatabaseHelper.TITLE, title.getText().toString());
values.put(DatabaseHelper.VALUE, value.getText().toString());
getActivity().getContentResolver().insert(Provider.Constants.CONTENT_URI, values);
getLoaderManager().restartLoader(0, null, this);
}
#Override
public void onListItemClick(ListView l, View v, int pos, long id) {
super.onListItemClick(l, v, pos, id);
getLoaderManager().restartLoader(0, null, this);
getActivity().getContentResolver().delete(Provider.Constants.CONTENT_URI,String.valueOf(id), null);
Toast.makeText(getActivity(), "Item id " + id + "clicked", Toast.LENGTH_SHORT).show();
}
private void add() {
LayoutInflater inflater=getActivity().getLayoutInflater();
View addView=inflater.inflate(R.layout.add_edit, null);
AlertDialog.Builder builder=new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.add_title).setView(addView)
.setPositiveButton(R.string.ok, this)
.setNegativeButton(R.string.cancel, null).show();
}
#Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
return new CursorLoader(getActivity().getApplicationContext(), Provider.Constants.CONTENT_URI, null, null, null, null);
}
public void insertNote(String title, Double value){
ContentValues values = new ContentValues();
values.put(DatabaseHelper.TITLE, title);
values.put(DatabaseHelper.VALUE, value);
Uri noteUri = getActivity().getContentResolver().insert(Provider.Constants.CONTENT_URI, values);
Log.d("MainActivity", "Inserted" + noteUri.getLastPathSegment());
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
cursorAdapter.swapCursor(cursor);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
cursorAdapter.swapCursor(null);
}
}

in on click after item deleted call to notifyDatasetChanged()

Related

CursorAdapter doesnt want to update

I made the delete posibility from cursor , the function works , but CursorAdapter doesnt update on notifyDataSetChanged(), any one has any idea ??? The only way at the moment to see the changes is to exit app and run again
public class DiaryFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemClickListener {
private GridView mGridView;
private View mEmptyViews;
private TextView mAddNewDiaryEntry;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_diary, container, false);
setHasOptionsMenu(true);
getLoaderManager().initLoader(0, null, this);
mGridView = (GridView) view.findViewById(R.id.gridview);
mGridView.setAdapter(new DiaryAdapter(getActivity()));
mGridView.setOnItemClickListener(this);
return view;
}
#Override
public void onResume() {
super.onResume();
GALogEvent.logScreen(getActivity(), "Diary");
getLoaderManager().restartLoader(0, null, this);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
getActivity().getMenuInflater().inflate(R.menu.diary, menu);
}
private CursorAdapter getAdapter() {
return ((CursorAdapter) mGridView.getAdapter());
}
public static Fragment newInstance() {
return new DiaryFragment();
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(getActivity(),ContentProvider. URI, null, null, null, ContentProvider.DIARY_DATE + " DESC");
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
getAdapter().swapCursor(data);
if (data != null && data.getCount() > 0) {
mGridView.setVisibility(View.VISIBLE);
mEmptyViews.setVisibility(View.GONE);
}
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
getAdapter().swapCursor(null);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
Cursor c = (Cursor) parent.getAdapter().getItem(position);
int diaryEntryId = c.getInt(c.getColumnIndex(ContentProvider.ID));
Intent intent = new Intent(getActivity(), AddDiaryEntryActivity.class);
boolean didSmoke = c.getInt(c.getColumnIndex(ContentProvider.DIARY_DID_SMOKE)) != 0;
intent.putExtra(Constants.DIARY_UPDATE_STATUS, didSmoke);
intent.putExtra(Constants.DIARY_ENTRY, diaryEntryId);
startActivity(intent);
}
private class DiaryAdapter extends CursorAdapter {
private final LayoutInflater mLayoutInflater;
public DiaryAdapter(Context context) {
super(context, null, true);
mLayoutInflater = LayoutInflater.from(context);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mLayoutInflater.inflate(R.layout.row_diary, parent, false);
}
#Override
public void bindView(View view, Context context, final Cursor cursor) {
final int idCraving = cursor.getInt(cursor.getColumnIndex(ContentProvider.ID));
final ImageView deleteDiaryEntry;
deleteDiaryEntry = (ImageView) view.findViewById(R.id.remove_registry_from_diary);
deleteDiaryEntry.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getActivity().getContentResolver().delete(ContentProvider. URI, " _id = ? ", new String[]{"" + idCraving});
getAdapter().notifyDataSetChanged();
}
});
}
}
}
Within the delete() method in your ContentProvider, you need to have the following line of code:
getContext().getContentResolver().notifyChange(uri, null);
From the official documentation, this line will notify CursorAdapter objects that a change occurred. If you do not have this line, you will see the change only when the code does a fresh lookup of the database which occurs when you exit and reopen the app.

Refresh custom cursor adapter after deleting database row

Sorry for my bad english and a stupid noob question.
I have a SimpleCursorAdapter and a ListView with Buttons on each item (row in database).
I realize deleting row but I don`t know how to refresh the ListView.
I hope that somebody can help me with simple and clear examples
my adapter
public class MySimpleCursorAdapter extends SimpleCursorAdapter {
Context context;
public MySimpleCursorAdapter(Context contxt, int layout, Cursor c, String[] from, int[] to, int flags) {
super(contxt, layout, c, from, to, flags);
context=contxt;
}
public View newView(Context _context, Cursor _cursor, ViewGroup parent){
LayoutInflater inflater = (LayoutInflater) _context.getSystemService(_context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.listform_item, parent, false);
return view;
}
#Override
public void bindView(View view, Context Context, Cursor cursor) {
String name = cursor.getString(cursor.getColumnIndex(DBHelper.FORM_NAME));
String title = cursor.getString(cursor.getColumnIndex(DBHelper.FORM_TITLE));
TextView formname = (TextView)view.findViewById(R.id.tvFormName);
formname.setText(name);
TextView formtitle=(TextView)view.findViewById(R.id.tvFormTitle);
formtitle.setText(title);
ImageButton yourButton = (ImageButton)view.findViewById(R.id.ibtnDelete);
yourButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(view != null) {
Object obj = view.getTag();
//if(obj != null && obj instanceof Integer) {
dbForm form=new dbForm(context);
form.open();
String st=obj.toString();
form.deleteForm(Long.valueOf(st).longValue());
Toast.makeText(context, "Delete row with id = " + st, Toast.LENGTH_LONG).show();
}
}
});
Object obj = cursor.getString(cursor.getColumnIndex(DBHelper.FORM_ID));
yourButton.setTag(obj);
}
}
I also use a CursorLoader in Main to acces the database
UPD: i use use cursor loader and a dont undertand how call his reset in my custom adapter, hope for help.
public class MainActivity extends FragmentActivity implements LoaderCallbacks<Cursor> {
ListView lvForms;
dbForm table_form;
SimpleCursorAdapter scAdapter;
/**
* Called when the activity is first created.
*/
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
table_form = new dbForm(this);
table_form.open();
String[] from = new String[]{DBHelper.FORM_NAME, DBHelper.FORM_TITLE};
int[] to = new int[]{R.id.tvFormName, R.id.tvFormTitle};
scAdapter = new MySimpleCursorAdapter(this, R.layout.listform_item, null, from, to, 0);
lvForms = (ListView) findViewById(R.id.lvForms);
lvForms.setAdapter(scAdapter);
registerForContextMenu(lvForms);
getSupportLoaderManager().initLoader(0, null, this);
}
public void onButtonClick(View view) {
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(intent);
}
protected void onDestroy() {
super.onDestroy();
table_form.close();
// закрываем подключение при выходе
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle bndl) {
return new MyCursorLoader(this, table_form);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
scAdapter.swapCursor(cursor);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
scAdapter.swapCursor(null);
}
static class MyCursorLoader extends CursorLoader {
dbForm table_form;
public MyCursorLoader(Context context, dbForm table_form) {
super(context);
this.table_form = table_form;
}
#Override
public Cursor loadInBackground() {
Cursor cursor = table_form.getAllData();
return cursor;
}
}
}
For a SimpleCursorAdapter it's best to use a CursorLoader like this :
public Loader<Cursor> onCreateLoader(int id,Bundle arg) {
return new SimpleCursorLoader(this) {
public Cursor loadInBackground() {
// This field reserved to what you want to load in your cursor adater and you return it (for example database query result)
// return Cursor ;
}
};
}
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
adapter.swapCursor(cursor);
}
public void onLoaderReset(Loader<Cursor> loader){
adapter.swapCursor(null);
}
And in your MainActivity or where you will instanciate the adapter, just before add this :
getLoaderManager().initLoader(0x01, null, this);
// declare your new Custom Simple Cursor Adapter here
scAdapter = new MySimpleCursorAdapter ....
And add :
public void onResume() {
super.onResume();
// Restart loader so that it refreshes displayed items according to database
getLoaderManager().restartLoader(0x01, null, this);
}
I work with loaders this way, I hope it helps you .
You should reload your cursor and update your cursor adapter:
// Reload your cursor here
Cursor newCursor = ….;
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD){
adapter.swapCursor(newCurosr);
} else {
adapter.changeCursor(newCursor);
}
Then, notify your list view about data changes:
adapter.notifyDataSetChanged();

Android ListFragment: how to have both onListItemClick and onContextItemSelected?

I'm implementing a ListActivity and ListFragment and would like to allow the user to use short taps and long taps - short being to edit/show the details of the item and long tap to bring up a context menu with the option to delete the item. I don't seem to be able to trigger the onCreateContextMenu, however. onListItemClick works fine and captures all taps, short or long. The ListFragment is populated using a slightly custom SimpleCursorAdaptor and LoaderManager, not using a layout file.
Is is possible to have both?
Code...
LocationsListFragment.java
package com.level3.connect.locations;
//import removed for brevity
public class LocationsListFragment extends SherlockListFragment implements LoaderManager.LoaderCallbacks<Cursor>{
private static final int DELETE_ID = Menu.FIRST + 1;
private SimpleCursorAdapter adapter;
private OnLocationSelectedListener locationSelectedListener;
// the activity attaching to this fragment should implement this interface
public interface OnLocationSelectedListener {
public void onLocationSelected(String locationId);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Fields from the database (projection)
// Must include the _id column for the adapter to work
String[] from = new String[] { LocationsTable.LOCATION_NAME,
LocationsTable.LOCATION_PHONE_NAME };
// Fields on the UI to which we map
int[] to = new int[] { R.id.titleText, R.id.phoneText };
// connect to the database
getLoaderManager().initLoader(0, null, this);
adapter = new LocationCursorAdapter(getActivity(),
R.layout.location_row, null, from, to, 0);
setListAdapter(adapter);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = super.onCreateView(inflater, container, savedInstanceState);
registerForContextMenu(root); //this is called fine
return root;
}
// hook up listening for the user selecting a location in the list
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
locationSelectedListener = (OnLocationSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnLocationSelectedListener");
}
}
// handle user tapping a location - show a detailed view - this works fine
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
String projection[] = { LocationsTable.KEY_ID };
Cursor locationCursor = getActivity().getContentResolver().query(
Uri.withAppendedPath(DatabaseContentProvider.CONTENT_URI,
String.valueOf(id)), projection, null, null, null);
if (locationCursor.moveToFirst()) {
String locationUrl = locationCursor.getString(0);
locationSelectedListener.onLocationSelected(locationUrl);
}
locationCursor.close();
}
// Context menu - this is never called
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.add(0, DELETE_ID, 0, R.string.menu_delete);
}
#Override - this is never called
public boolean onContextItemSelected(android.view.MenuItem item) {
switch (item.getItemId()) {
case DELETE_ID:
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
.getMenuInfo();
Uri uri = Uri.parse(DatabaseContentProvider.CONTENT_URI + "/"
+ info.id);
getActivity().getContentResolver().delete(uri, null, null);
return true;
}
return super.onContextItemSelected(item);
}
// Loader code
// Creates a new loader after the initLoader () call
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = { LocationsTable.KEY_ID, LocationsTable.LOCATION_NAME, LocationsTable.LOCATION_PHONE_NAME };
CursorLoader cursorLoader = new CursorLoader(getActivity(),
DatabaseContentProvider.CONTENT_URI, projection, null, null, null);
return cursorLoader;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
adapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
// data is not available anymore, delete reference
adapter.swapCursor(null);
}
}
UPDATE: I still have not figured this out and am wondering if I have to abandon this strategy and implement it in some other, not as user-friendly manner. Perhaps a swipe to view details and a tap to delete?
I've found my answer in the Android source code for the native Email app. https://android.googlesource.com/platform/packages/apps/Email/
The ListFragment must implement listeners:
public class MessageListFragment extends SherlockListFragment
implements LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemLongClickListener
private static final int DELETE_ID = Menu.FIRST + 1;
private SimpleCursorAdapter adapter;
// The LoaderManager needs initializing
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Fields from the database (projection)
// Must include the _id column for the adapter to work
String[] from = new String[] { BookmarksTable.BOOKMARK_NAME,
BookmarksTable.BOOKMARK_PHONE_NAME };
// Fields on the UI to which we map
int[] to = new int[] { R.id.titleText, R.id.phoneText };
// connect to the database
getLoaderManager().initLoader(0, null, this);
adapter = new BookmarkCursorAdapter(getActivity(),
R.layout.bookmark_row, null, from, to, 0);
setListAdapter(adapter);
}
// register to put up the context menu
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = super.onCreateView(inflater, container, savedInstanceState);
registerForContextMenu(root);
return root;
}
// set the listeners for long click
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
getListView().setOnItemLongClickListener(this);
}
The called methods are:
/**
* Called when a message is clicked.
*/
#Override
public void onListItemClick(ListView parent, View view, int position, long id) {
// do item click stuff; show detailed view in my case
}
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
return false; // let the system show the context menu
}
// Context menu
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.add(0, DELETE_ID, 0, R.string.menu_delete);
}
// respond to the context menu tap
#Override
public boolean onContextItemSelected(android.view.MenuItem item) {
switch (item.getItemId()) {
case DELETE_ID:
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
.getMenuInfo();
Uri uri = Uri.parse(DatabaseContentProvider.BOOKMARK_ID_URI + Long.toString(info.id));
getActivity().getContentResolver().delete(uri, null, null);
return true;
}
return super.onContextItemSelected(item);
}
For completeness, here's the loader code
// Loader code
// Creates a new loader after the initLoader () call
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = { BookmarksTable.KEY_ID, BookmarksTable.BOOKMARK_NAME, BookmarksTable.BOOKMARK_PHONE_NAME };
CursorLoader cursorLoader = new CursorLoader(getActivity(),
DatabaseContentProvider.BOOKMARKS_URI, projection, null, null, null);
return cursorLoader;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
adapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
// data is not available anymore, delete reference
adapter.swapCursor(null);
}

listview not refresh even after calling restart loader

I have List fragment with Context menu on long press of list item. The list item clicked and the list item removed from my Database. But the list not refresh even after calling restart loader?
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setEmptyText("Loading...");
myAdapter = new MySimpleCursorAdapter(getActivity().getApplicationContext(), R.layout.my_list_item, null, new String[] {DBConstants.NAME,DBConstants.ITEM1,DBConstants.SYMBOL}, new int[] {R.id.my_companyname,R.id.my_item1,R.id.my_symbol},0);
setListAdapter(myAdapter);
registerForContextMenu(getListView());
MyLoader = getActivity().getSupportLoaderManager().initLoader(1, null, this);
}
#Override
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
DBHelper dbHelper=new DBHelper(getActivity());
return new MyLoader(getActivity(),dbHelper);
}
#Override
public void onLoadFinished(Loader<Cursor> arg0, Cursor c) {
if(c!=null && c.getCount()>0){
myAdapter.swapCursor(c);
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
else
{
setEmptyText("Not selected");
}
}
#Override
public void onLoaderReset(Loader<Cursor> arg0) {
myAdapter.swapCursor(null);
}
#Override
public boolean onContextItemSelected(MenuItem item) {
String selectedItem = item.getTitle().toString();
Log.i("context", "selected context menu item->"+selectedItem);
if(selectedItem.equalsIgnoreCase("Remove"))
{
AdapterView.AdapterContextMenuInfo menuInfo=(AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
String[] args={String.valueOf(menuInfo.id)};
Log.i("context", String.valueOf(menuInfo.id));
new DBHelper(getActivity()).getWritableDatabase().delete(DBConstants.MYSTOCKS_TABLE, "_ID=?", args);
getActivity().getSupportLoaderManager().restartLoader(1, null, this);
/*
Cursor cursor = myAdapter.getCursor();
myAdapter.swapCursor(cursor);
*/
//getLoaderManager().initLoader(0, null, this);
}
return super.onContextItemSelected(item);
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) {
//super.onCreateContextMenu(menu, v, menuInfo);
getActivity().getMenuInflater().inflate(R.menu.mystocks_context, menu);
}
Do you add the fragment in activity's onCreate or onResume? If the latter, you might want to move the fragment setup (transaction creation, addition of the fragment, committing) to onCreate. After doing that restartLoader() will work properly.

SherlockListFrgament with CommonsWare Loaderex, can't update data

public class NewFriendsListFragment extends SherlockListFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
int monthchange, daychange;
Dialog dialog;
int pos;
CheckedTextView ctv_name;
private SimpleCursorAdapter mAdapter=null;
private SQLiteCursorLoader loader=null;
String mCurFilter;
private static Handler responseHandler;
boolean loaded=false;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//some more stuff...
setHasOptionsMenu(true);
mAdapter = new FriendListSCA(getSherlockActivity().getApplicationContext(),
R.layout.friend_item, null,null, null, null, null, NAME),
new String[]{NAME,MONTH,UID}, new int[]{R.id.name,R.id.info,R.id.profile_pic});
setListAdapter(mAdapter);
setListShown(false);
registerForContextMenu(getListView());
getLoaderManager().initLoader(0, null, this);
responseHandler = new Handler()
{
//handler code
};
}
public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) {
//loader code
return(loader);
}
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
mAdapter.changeCursor(cursor);
// Showin List
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.changeCursor(null);
}
#Override
public boolean onContextItemSelected(android.view.MenuItem item) {
AdapterContextMenuInfo info;
try {
info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
} catch (ClassCastException e) {
return false;
}
pos=info.position;
switch (item.getItemId()) {
case R.id.edit_item:
show_dialog();
return true;
}
return(super.onOptionsItemSelected(item));
}
#Override
public void onListItemClick(ListView l, View v, final int position, long id) {
Log.e("onListItemClick","Inside onListItemClick");
ContentValues cv= new ContentValues();
//MORE CODE
loader.update(TABLE_NAME_INCLUDE, cv, _ID+" = ?", new String[]{Integer.toString(position)});
}
private class FriendListSCA extends SimpleCursorAdapter
{
public FriendListSCA(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to,0);
setViewBinder(new FriendsListDataViewBinder());
}
}
public class FriendsListDataViewBinder implements SimpleCursorAdapter.ViewBinder
{
//_ID + "," + UID+","+NAME+","+MONTH+","+DAY+","+WISH
#Override
public boolean setViewValue(View view, Cursor c, int columnIndex)
{
switch (view.getId())
{
case R.id.name:
CheckedTextView ctv= (CheckedTextView)view;
ctv.setText(c.getString(2));
if(c.getInt(5)==0 || c.getInt(4)==-1)
{
ctv.setPaintFlags(ctv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
ctv.setChecked(false);
}
else
{
ctv.setPaintFlags(ctv.getPaintFlags() & (~ Paint.STRIKE_THRU_TEXT_FLAG));
ctv.setChecked(true);
}
return true;
case R.id.info:
if(c.getInt(4)!=-1)
{
((TextView)view).setText(Utility.MONTH_NAME[c.getInt(3)-1] + " " + Integer.toString(c.getInt(4)));
}
else
{
((TextView)view).setText("Tap and hold to manually enter");
}
return true;
case R.id.profile_pic:
if(!loaded)
return true;
((ImageView)view).setImageBitmap(Utility.model.getImage(
Long.toString( c.getLong(1) ), getURL(c.getLong(1)) ));
return true;
}
return false;
}
}
private void show_dialog()
{
//DATE PICKER CODE
okay.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v)
{
ContentValues cv=new ContentValues();
cv.put(MONTH, monthchange);
cv.put(DAY, daychange);
loader.update(TABLE_NAME_INCLUDE, cv, _ID+" = ?" , new String[]{Integer.toString(pos)});
//getLoaderManager().restartLoader(0, null, NewFriendsListFragment.this);
//I tried calling restart loader, but nothing, when I checked
//it turned out the sqlite database wasn't being updated
responseHandler.sendEmptyMessage(1); //just dismisses dialog
}
});
dialog.show();
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Place an action bar item for searching.
MenuItem item = menu.add("Search");
item.setIcon(android.R.drawable.ic_menu_search);
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
View searchView = SearchViewCompat.newSearchView(getActivity());
if (searchView != null) {
SearchViewCompat.setOnQueryTextListener(searchView,
new OnQueryTextListenerCompat() {
#Override
public boolean onQueryTextChange(String filtext) {
mCurFilter = !TextUtils.isEmpty(filtext) ? filtext : null;
getLoaderManager().restartLoader(0, null, NewFriendsListFragment.this);
return true;
}
});
item.setActionView(searchView);
}
}
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
}
}
I'm using a SherlockListFragment from the ActionBarSherlock library to display a list using a CommonsWare Loaderex sqlite cursor loader, and evrything seems to work fine, the names and birthdays and profile pics are all displayed fine, but I can't seem to be able to update any of the data in the table using loader.update(...), nothing happens when I call it.
What's wrong?
You have:
loader.update(TABLE_NAME_INCLUDE, cv, _ID+" = ?", new String[]{Integer.toString(position)});
In all likelihood, that should be:
loader.update(TABLE_NAME_INCLUDE, cv, _ID+" = ?", new String[]{Integer.toString(id)});
(replacing position with id)

Categories

Resources