Java tutorial
/* * Copyright (C) 2012 Davy Leggieri * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package com.bydavy.card.receipts.fragments; import java.util.ArrayList; import java.util.Set; import android.app.Activity; import android.content.ContentProviderOperation; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.AdapterView.OnItemLongClickListener; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ListView; import android.widget.Toast; import com.actionbarsherlock.view.ActionMode; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import com.bydavy.card.receipts.R; import com.bydavy.card.receipts.ReceiptListAdapter; import com.bydavy.card.receipts.ReceiptListAdapter.Callback; import com.bydavy.card.receipts.providers.Receipts; import com.bydavy.card.receipts.providers.ReceiptsProvider; import com.bydavy.card.receipts.utils.Config; import com.bydavy.card.receipts.utils.DebugThreads; import com.bydavy.card.receipts.utils.LogHelper; import com.bydavy.card.receipts.utils.LogHelper.ErrorID; public class ReceiptListFragment extends StateSherlockListFragment implements Callback, OnItemLongClickListener, OnItemSelectedListener { /** Change first statement of if condition to enable class debug **/ private static final boolean DEBUG = LogHelper.DEBUG ? false : LogHelper.DEFAULT_DEBUG; private static final String DEBUG_PREFIX = ReceiptListFragment.class.getName(); public interface OnReceiptListChangeListener { void onReceiptListSelected(int index); } private static final String ARG_SELECTION = "selection"; private static final String ARG_SELECTION_ARGS = "selectionArgs"; private static final String ARG_SORTORDER = "sortOrder"; private static final String STATE_ITEM_SELECTED = "receiptListSelected"; private static final int CURSOR_LOADER_RECEIPT_LIST = 0; private ActionMode mActionMode; private final ActionMode.Callback mActionModeCallback = new MyActionModeCallback(); private ReceiptListAdapter mAdapter; private int mIndex; private boolean mDualPane; private final ReceiptsCursorLoader mLoaderCallBack = new ReceiptsCursorLoader(); private OnReceiptListChangeListener mOnReceiptListChangeListener; public static ReceiptListFragment newInstance(String selection, String[] selectionArgs, String sortOrder) { final ReceiptListFragment f = new ReceiptListFragment(); final Bundle args = new Bundle(); args.putString(ARG_SELECTION, selection); args.putStringArray(ARG_SELECTION_ARGS, selectionArgs); args.putString(ARG_SORTORDER, sortOrder); f.setArguments(args); return f; } public String getCursorSelection() { final Bundle args = getArguments(); if (args != null) { return args.getString(ARG_SELECTION); } return null; } public String[] getCursorSelectionArgs() { final Bundle args = getArguments(); if (args != null) { return args.getStringArray(ARG_SELECTION_ARGS); } return new String[0]; } public String getCursorSortOrder() { final Bundle args = getArguments(); if (args != null) { return args.getString(ARG_SORTORDER); } return null; } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mOnReceiptListChangeListener = (OnReceiptListChangeListener) activity; } catch (final ClassCastException e) { LogHelper.e(ErrorID.IMPLEMENTATION, "Activity must implement " + OnReceiptListChangeListener.class.getName(), e); throw e; } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mAdapter = new ReceiptListAdapter(getActivity(), R.layout.fragment_receipt_list__item, null, ReceiptListFragment.this); if (savedInstanceState != null) { mIndex = savedInstanceState.getInt(STATE_ITEM_SELECTED); mAdapter.load(savedInstanceState); } else { mIndex = 0; } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_receipt_list, null); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); final ListView listView = getListView(); listView.setOnItemSelectedListener(this); listView.setOnItemLongClickListener(this); setListAdapter(mAdapter); if (mDualPane) { listView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE); } final Bundle bundle = mLoaderCallBack.createLoaderBundle(getCursorSelection(), getCursorSelectionArgs(), getCursorSortOrder()); getLoaderManager().initLoader(CURSOR_LOADER_RECEIPT_LIST, bundle, mLoaderCallBack); } @Override public void onSaveInstanceState(Bundle outState) { outState.putInt(STATE_ITEM_SELECTED, mIndex); mAdapter.save(outState); super.onSaveInstanceState(outState); } @Override public void onAdapterSelectedChanged(boolean newSelected, int selectedCount) { if (Config.CHECK_THREADS) { DebugThreads.throwIfNotMainThread(); } if (selectedCount > 0) { if (mActionMode == null) { mActionMode = getSherlockActivity().startActionMode(mActionModeCallback); } final String text = String.format(getString(R.string.action_mode_selected), selectedCount); mActionMode.setTitle(text); } else { if (mActionMode != null) { mActionMode.finish(); mActionMode = null; } } }; public int getItemSelected() { if (Config.CHECK_THREADS) { DebugThreads.throwIfNotMainThread(); } return mIndex; } @Override public void onListItemClick(ListView l, View v, int position, long id) { mOnReceiptListChangeListener.onReceiptListSelected(position); } @Override public boolean onItemLongClick(AdapterView<?> adapter, View v, int position, long id) { Toast.makeText(getActivity(), "Long click", Toast.LENGTH_LONG).show(); return false; } @Override public void onItemSelected(AdapterView<?> adapter, View view, int position, long id) { mIndex = position; } @Override public void onNothingSelected(AdapterView<?> adapter) { } private final class MyActionModeCallback implements ActionMode.Callback { @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { final MenuInflater inflater = getSherlockActivity().getSupportMenuInflater(); inflater.inflate(R.menu.fragment_receipt_list__action_mode, menu); return true; } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { final Set<Long> concernedIds = mAdapter.getSelectedSet(); switch (item.getItemId()) { case R.id.menu_delete: { final ArrayList<ContentProviderOperation> operation = new ArrayList<ContentProviderOperation>(); for (final Long id : concernedIds) { final Uri uri = Uri.withAppendedPath(Receipts.CONTENT_URI, String.valueOf(id)); operation.add(ContentProviderOperation.newDelete(uri).build()); } try { getActivity().getContentResolver().applyBatch(ReceiptsProvider.AUTHORITY, operation); } catch (final Exception e) { LogHelper.e(ErrorID.CONTENT_PROVIDER, DEBUG_PREFIX + ": " + e, e); } break; } case R.id.menu_verified: { final ArrayList<ContentProviderOperation> operation = new ArrayList<ContentProviderOperation>(); for (final Long id : concernedIds) { final Uri uri = Uri.withAppendedPath(Receipts.CONTENT_URI, String.valueOf(id)); operation.add(ContentProviderOperation.newUpdate(uri) .withValue(Receipts.COLUMN_NAME_VERIFIED, true).build()); } try { getActivity().getContentResolver().applyBatch(ReceiptsProvider.AUTHORITY, operation); } catch (final Exception e) { LogHelper.e(ErrorID.CONTENT_PROVIDER, DEBUG_PREFIX + ": " + e, e); } break; } case R.id.menu_non_verified: { final ArrayList<ContentProviderOperation> operation = new ArrayList<ContentProviderOperation>(); for (final Long id : concernedIds) { final Uri uri = Uri.withAppendedPath(Receipts.CONTENT_URI, String.valueOf(id)); operation.add(ContentProviderOperation.newUpdate(uri) .withValue(Receipts.COLUMN_NAME_VERIFIED, false).build()); } try { getActivity().getContentResolver().applyBatch(ReceiptsProvider.AUTHORITY, operation); } catch (final Exception e) { LogHelper.e(ErrorID.DATABASE, DEBUG_PREFIX + ": " + e, e); } break; } default: } mode.finish(); return true; } @Override public void onDestroyActionMode(ActionMode mode) { mAdapter.clearSelected(); mActionMode = null; } } private final class ReceiptsCursorLoader implements LoaderCallbacks<Cursor> { private static final String BUNDLE_SELECTION = "selection"; private static final String BUNDLE_SELECTION_ARGS = "selectionArgs"; private static final String BUNDLE_SORT_ORDER = "sortOrder"; /* Not possible to create a static method =0/ */ public Bundle createLoaderBundle(String selection, String[] selectionArgs, String sortOrder) { final Bundle bundle = new Bundle(); bundle.putString(BUNDLE_SELECTION, selection); bundle.putStringArray(BUNDLE_SELECTION_ARGS, selectionArgs); bundle.putString(BUNDLE_SORT_ORDER, sortOrder); return bundle; } /* Dedicated thread */ @Override public Loader<Cursor> onCreateLoader(int id, Bundle bundle) { switch (id) { case CURSOR_LOADER_RECEIPT_LIST: if (bundle == null) { throw new IllegalArgumentException("Must use a bundle"); } final String selection = bundle.getString(BUNDLE_SELECTION); final String[] selectionArgs = bundle.getStringArray(BUNDLE_SELECTION_ARGS); final String sortOrder = bundle.getString(BUNDLE_SORT_ORDER); return new CursorLoader(getActivity(), Receipts.CONTENT_URI, null, selection, selectionArgs, sortOrder); default: throw new IllegalArgumentException("The cursor loader " + id + "doesn't exist"); } } /* UIThread */ @Override public void onLoadFinished(Loader<Cursor> cl, Cursor cursor) { mAdapter.changeCursor(cursor); final ListView listView = getListView(); if (getState() != StateFragmentListener.STATE_COMPLETED) { if (mDualPane) { listView.setItemChecked(mIndex, true); } listView.setSelectionFromTop(mIndex, 0); setState(StateFragmentListener.STATE_COMPLETED); } } /* UIThread */ @Override public void onLoaderReset(Loader<Cursor> cursor) { } } }