How can I change what the ActionBar menu contains depending on how many items in a RecyclerView are selected? For instance, when one card is selected in 'selection mode,' I want an Edit icon (pencil) visible. As soon as more than one item is selected, I want the Edit icon to disappear from the options.
The code below: I tried to create a condition in which mDeletionMode creates a menu with an Edit icon present if the number of selected items was <= 1 , and create a menu without the pencil if the number was more than one. My approach was foolish, as I realize that the menu is only created after an item experiences a longClick, and of course only one item would have been selected at that point. I left the dumb-dumb code I used to try this just to show my approach, while what I am actually looking for is the following:
public class SubjectManagerFragment extends BaseFragment implements ActionMode.Callback {
public static ArrayList<SubjectInfo> subjectList = new ArrayList<SubjectInfo>();
public static FloatingActionButton fabCreateSubject;
private AlertDialog.Builder build;
private MultiSelector mMultiSelector = new MultiSelector();
public ActionMode actionMode;
public RecyclerView recList;
public CardView cardView;
public ItemClickSupport itemClick;
// currently an adaptation from:
// https://github.com/bignerdranch/recyclerview-multiselect#modal-multiselection-with-long-click
public ActionMode.Callback mDeleteMode = new ModalMultiSelectorCallback(mMultiSelector) {
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
super.onCreateActionMode(actionMode, menu);
if (mMultiSelector.getSelectedPositions().size() <= 1) {
getActivity().getMenuInflater().inflate(R.menu.menu_subject_manager, menu);
} else {
getActivity().getMenuInflater().inflate(R.menu.menu_subject_manager_multiple, menu);
}
return true;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.action_select_all:
// Delete crimes from model
//actually do nothing.
mMultiSelector.clearSelections();
return true;
default:
break;
}
return false;
}
};
public static final String ARG_PARAM1 = "param1";
public static final String ARG_PARAM2 = "param2";
private String mParam1;
private String mParam2;
public static SubjectManagerFragment newInstance(String param1, String param2) {
SubjectManagerFragment fragment = new SubjectManagerFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
public SubjectManagerFragment() {
// Required empty public constructor
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
}
//non graphical initialization
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(false);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View smFragmentView = inflater.inflate(R.layout.fragment_subject_manager, container, false);
recList = (RecyclerView) smFragmentView.findViewById(R.id.subject_card_list);
cardView = (CardView) smFragmentView.findViewById(R.id.subject_card);
recList.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
llm.setOrientation(LinearLayoutManager.VERTICAL);
subjectList = getSubjectInfoArrayList();
recList.setLayoutManager(llm);
recList.setAdapter(new CrimeAdapter());
fabCreateSubject = (FloatingActionButton) smFragmentView.findViewById(R.id.fab_create_subject);
fabCreateSubject.setOnClickListener (new View.OnClickListener() {
#Override
public void onClick(View v) {
build = new AlertDialog.Builder(getActivity());
LayoutInflater inflater1 = getActivity().getLayoutInflater();
View alertview = inflater1.inflate(R.layout.create_subject_dialog, null);
// Pass null as the parent view because its going in the dialog layout
build.setView(alertview);
final EditText inputSubjectName = (EditText) alertview.findViewById(R.id.dialog_edit_subject_card_name);
final EditText inputSubjectGrade = (EditText) alertview.findViewById(R.id.dialog_edit_subject_card_grade);
build.setTitle("Add Subject");
build.setPositiveButton("Save", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
String enteredSubjectName = inputSubjectName.getText().toString();
int enteredSubjectGrade = Integer.parseInt("0" + inputSubjectGrade.getText().toString()); //was getting stupid error from null value going to int?
boolean enteredSubjectIsArchived = false;
if (subjectCanBeEntered(inputSubjectName, inputSubjectGrade, subjectList)) {
SubjectInfo si = new SubjectInfo(enteredSubjectName, "Assignments", enteredSubjectGrade, enteredSubjectIsArchived, true);
si.save();
subjectList.add(si);
getActivity().recreate();
sa.notifyDataSetChanged();
recList.smoothScrollToPosition(subjectList.size()-1);
} //will need to check if subject already exists, but YOLO for now.
dialog.cancel();
}
});
build.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = build.create();
alert.show();
}
});
// Inflate the layout for this fragment
return smFragmentView;
}
public ArrayList<SubjectInfo> getSubjectInfoArrayList(){
ArrayList<SubjectInfo> sial= new ArrayList<SubjectInfo>();
List<SubjectInfo> sil = SubjectInfo.listAll(SubjectInfo.class);
sial.addAll(sil);
for (int go = 0; go <sial.size(); go++) {
if (sial.get(go).itemHeaderTitle.equals("Archived")) {
sial.remove(go);
}
}
return sial;
}
public boolean subjectCanBeEntered (EditText inputName, EditText inputGrade, ArrayList<SubjectInfo> aList) {
boolean enterable = true;
if ((inputName.getText().toString().equals(""))) {
enterable = false;
Toast.makeText(
getActivity().getApplicationContext(), "Enter a class name.", Toast.LENGTH_SHORT).show();
}
if ((inputGrade.getText().toString().equals(""))) { // I don't think hint is picked up
enterable = false;
Toast.makeText(
getActivity().getApplicationContext(), "Enter a grade.", Toast.LENGTH_SHORT).show();
}
for (int go = 0; go < aList.size(); go++) {
if (inputName.getText().toString().equals(aList.get(go).subjectName)) {
enterable = false;
Toast.makeText(
getActivity().getApplicationContext(), "You've already saved a class with that name.", Toast.LENGTH_LONG).show();
}
}
return enterable;
}
private class CrimeHolder extends SwappingHolder
implements View.OnClickListener, View.OnLongClickListener {
protected TextView vSubjectName;
protected EditText vSubjectGrade;
protected RelativeLayout vSubjectLayout;
private SubjectInfo sInfo;
public CrimeHolder(View itemView) {
super(itemView, mMultiSelector);
vSubjectName = (TextView) itemView.findViewById(R.id.subject_card_name_textView);
vSubjectGrade = (EditText) itemView.findViewById(R.id.subject_card_grade_editText);
vSubjectLayout = (RelativeLayout) itemView.findViewById(R.id.subject_card_relative_layout);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
itemView.setLongClickable(true);
}
public void bindCrime(SubjectInfo si) {
sInfo = si;
vSubjectName.setText(sInfo.subjectName);
vSubjectGrade.setText(Integer.toString(si.subjectGrade));
vSubjectLayout.setBackgroundColor(Color.parseColor(SubjectAdapter.giveSubjectHexValue((double) si.subjectGrade)));
}
#Override
public void onClick(View v) {
if (sInfo == null) {
return;
}
if (!mMultiSelector.tapSelection(this)) {
// This condition is the same as, if not in ActionMode, handle the click normally:
//getActionBar().startActionMode(mDeleteMode);
}
}
#Override
public boolean onLongClick(View v) {
//ActionBarActivity activity = (ActionBarActivity)getActivity();
getActionBar().startActionMode(mDeleteMode);
mMultiSelector.setSelected(this, true);
return true;
}
}
private class CrimeAdapter extends RecyclerView.Adapter<CrimeHolder> {
#Override
public CrimeHolder onCreateViewHolder(ViewGroup parent, int pos) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.subject_card_layout, parent, false);
return new CrimeHolder(view);
}
#Override
public void onBindViewHolder(CrimeHolder holder, int pos) {
SubjectInfo sInfo = subjectList.get(pos);
holder.bindCrime(sInfo);
}
#Override
public int getItemCount() {
return subjectList.size();
}
}
}
SO my question is: how to programmatically either remove/add the Edit icon OR switch to the other menu (with one fewer option) depending on how may items are selected.
Use an ActionMode instance to manipulate the ActionBar menu.
#Override
public boolean onLongClick(View v) {
this.actionMode = getActionBar().startActionMode(mDeleteMode);
mMultiSelector.setSelected(this, true);
return true;
}
Below is where your menuItem gets initialized. Keep in mind that onCreateActionMode resides in the creation of the new ModalMultiSelectorCallback.
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
super.onCreateActionMode(actionMode, menu);getActivity().getMenuInflater().inflate(R.menu.menu_subject_manager, menu);
mEditItem = actionMode.getMenu().findItem(R.id.action_edit);
mActionMenu = actionMode.getMenu();
return true;
}
Now, mEditItem can be removed or replaced with ease, as mEditItem is an instance variable. I'll provide my implementation in my onClick()
#Override
public void onClick(View v) {
if (sInfo == null) {
return;
}
if (!mMultiSelector.tapSelection(this)) {
// if not in selection mode, this is handled
}
if (mMultiSelector.tapSelection(this)) {
mMultiSelector.tapSelection(this);
switch (mMultiSelector.getSelectedPositions().size()) {
case 0:
actionMode.finish();
break;
case 1:
mEditItem.setVisible(true);
break;
case 2:
mEditItem.setVisible(false);
break;
default:
break;
}
}
}
And there I have it. For me, I just needed an item to disappear/reappear according to how many items were selected at any given moment. The .setVisible() method took care of this for me. I hope this helps someone with a similar issue!
Related
I'm writing a memo keeper app. It has a ViewPager that allows you to swipe between categories of memos. When I add a memo in a page, the memo is listed in the ListView of the fragment.
But if i swipe to another page and swipe back, then add another memo, that memo is not listed in the ListView. I tried notifyDatasetChanged() of the adapter and invalidateViews() of the ListView but nothing seem to work.
I don't know, where I made a mistake. I hope if you can find what I did wrong, it will very helpful for me.
Here is my Fragment code:
public class MemoListFragment extends Fragment
{
private MemoAdapter memoAdapter = null;
private ListView memoListView;
private Memo memoToEdit = null;
private List<Memo> userSelected = new ArrayList<>();
private onDeleteActionSelectedListener
deleteActionSelectedListener;
private String category;
private List<Memo> memoList;
public String getCategory()
{
return category;
}
public void setCategory(String category)
{
this.category = category;
}
private final int EDIT_MEMO_REQUEST_CODE = 2;
public void updateMemoList(List<Memo> memoList)
{
memoAdapter.clear();
memoAdapter.addAll(memoList);
}
public void setInitData(List<Memo> memoList)
{
this.memoList = memoList;
}
public void addMemo(Memo m)
{
memoAdapter.add(m);
memoListView.invalidateViews();
}
public MemoListFragment()
{
// Required empty public constructor
}
#Override
public void onAttach(Context context)
{
super.onAttach(context);
deleteActionSelectedListener = ((MainActivity)
context).getMainPresenter();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container,
Bundle savedInstanceState)
{
View rootLayout = inflater.inflate(R.layout.memo_list_fragment,
container, false);
memoListView = rootLayout.findViewById(R.id.memo_list_view);
memoListView.setOnItemClickListener((parent, view, position,
id) ->
{
{
Memo selectedMemo = memoAdapter.getItem(position);
Intent editMemo = new Intent(getActivity(),
MemoViewActivity.class);
editMemo.putExtra("memo_to_edit", selectedMemo);
memoToEdit = selectedMemo;
startActivityForResult(editMemo,
EDIT_MEMO_REQUEST_CODE);
}
});
memoAdapter = new MemoAdapter(getActivity(), 0, memoList);
memoListView.setAdapter(memoAdapter);
memoListView.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE_MODAL);
memoListView.setMultiChoiceModeListener(modeListener);
return rootLayout;
}
#Override
public void onActivityResult(int requestCode, int resultCode,
Intent data)
{
if (requestCode == EDIT_MEMO_REQUEST_CODE)
{
if (resultCode == Activity.RESULT_OK)
{
String title = data.getStringExtra("title").toString();
String detail =
data.getStringExtra("detail").toString();
if (memoToEdit != null)
{
memoToEdit.setDetail(detail);
memoToEdit.setTitle(title);
memoToEdit.setLastModified(LocalDate.now());
memoToEdit = null;
}
}
}
}
AbsListView.MultiChoiceModeListener modeListener = new
AbsListView.MultiChoiceModeListener()
{
#Override
public void onItemCheckedStateChanged(ActionMode mode, int
position, long id, boolean checked)
{
Memo m = memoAdapter.getItem(position);
if (userSelected.contains(m))
{
userSelected.remove(m);
memoAdapter.getSelectedPos().remove(new
Integer(position));
}
else
{
userSelected.add(m);
memoAdapter.getSelectedPos().add(position);
}
memoListView.invalidateViews();
mode.setTitle(userSelected.size() + " items selected.");
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu)
{
mode.getMenuInflater().inflate(R.menu.context_menu, menu);
memoAdapter.setShowCheckboxes(true);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu)
{
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem
item)
{
switch (item.getItemId())
{
case R.id.action_delete:
for (Memo m : userSelected)
memoAdapter.remove(m);
deleteActionSelectedListener.onDeleteActionSelected(userSelected);
mode.finish();
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode mode)
{
userSelected.clear();
memoAdapter.getSelectedPos().clear();
memoAdapter.setShowCheckboxes(false);
}
};
public interface onDeleteActionSelectedListener
{
void onDeleteActionSelected(List<Memo> userSelected);
}
}
Here is the code to add a memo:
public void addMemo(Memo memo)
{
int currentPage = mainView.getCurrentPagePosition();
if (currentPage == 0)//on page All category
memo.setCategory("Not categorized");
else
memo.setCategory(memoManager.getCategoriesList().get(currentPage));
MemoListFragment currentFrag = fragmentList.get(currentPage);
currentFrag.addMemo(memo);
}
Here is my PagerAdapter code:
public class MemooPagerAdapter extends FragmentStatePagerAdapter
{
private FragmentSetupManager fragmentSetupManager;
private List<String> categoriesList;
public MemooPagerAdapter(FragmentManager fm, FragmentSetupManager fragmentSetupManager)
{
super(fm);
this.fragmentSetupManager = fragmentSetupManager;
this.categoriesList = fragmentSetupManager.getCategoriesList();
}
#Override
public Fragment getItem(int position)
{
MemoListFragment fragment = new MemoListFragment();
String cate = categoriesList.get(position);
fragment.setCategory(cate);
fragment.setInitData(fragmentSetupManager.getFragmentData(cate));
fragmentSetupManager.addToFragmentList(fragment);
return fragment;
}
#Override
public int getCount()
{
return categoriesList.size();
}
#Nullable
#Override
public CharSequence getPageTitle(int position)
{
return categoriesList.get(position);
}
public interface FragmentSetupManager
{
List<Memo> getFragmentData(String category);
void addToFragmentList(MemoListFragment fragment);
List<String> getCategoriesList();
}
}
ViewPager stetup:
public MainPresenter(MainView mainView)
{
this.mainView = mainView;
memoManager = new MemoManager(((Activity) mainView).getApplicationContext());
pagerAdapter = new MemooPagerAdapter(
((FragmentActivity) mainView).getSupportFragmentManager(), this);
mainView.setMainVPagerAdapter(pagerAdapter);
}
Ideally, you want to communicate an event from one fragment to another. The easiest of ways is to use RXJava. This approach is the best way of doing that and easy to implement. In my opinion, this is the best approach for communicating two or maore fragments in Android.
Set up your project with the dependencies:
// RxJava2 Dependencies
implementation 'io.reactivex.rxjava2:rxjava:2.2.8'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
So if you are in FragmentA and move to FragmentB, and made a change in FragmentB, FragmentA will get this change.
See how this was implemented easily here. Do let me know if it is sufficient.
Hello friends.
I have navigation drawer with a menu item when clicking on each menu nav item, one fragment loaded, inside this fragments, I have recycled view items. Now I want use searchView filter for this items. I created a searchView icon in the toolbar, and write codes for SearchView inside Adapter(setFilter) and etc, but nothing happen when writing names item.
this is my fragment.
AfricaFragment`
public class AfricaFragment extends Fragment implements SearchView.OnQueryTextListener {
public static final String AFRICA_FRAGMENT = "africa_fragment";
ArrayList<AsiaCountry> asiaCountries = new ArrayList<>();
ContentAdapter contentAdapter;
RecyclerView recyclerView;
//FastScroller fastScroller;
private boolean isListView;
private Menu menu;
private StaggeredGridLayoutManager staggeredGridLayoutManager;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
//The parameter value of false indicates that container is to be used
// only for the layout parameters.
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.africa_fragment, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
// fastScroller = (FastScroller) view.findViewById(R.id.fast_scrollview);
isListView = true;
loadDataBase();
return view;
}
public void toggle() {
MenuItem item = menu.findItem(R.id.grid);
if (isListView) {
staggeredGridLayoutManager.setSpanCount(2);
item.setIcon(R.drawable.ic_vertical);
item.setTitle("Show as list");
isListView = false;
} else {
staggeredGridLayoutManager.setSpanCount(1);
item.setIcon(R.drawable.ic_grid);
item.setTitle("Show grid");
isListView = true;
}
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.grid_item, menu);
this.menu = menu;
Log.d("Menu created", "grid");
final MenuItem menuItem = menu.findItem(R.id.search);
SearchView searchView = (SearchView)
MenuItemCompat.getActionView(menuItem);
searchView.setOnQueryTextListener(this);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.grid) {
Toast.makeText(getActivity(), "Grid item touched", Toast.LENGTH_SHORT).show();
toggle();
return true;
}
if (id == R.id.settings) {
Toast.makeText(getActivity(), "Setting clicked", Toast.LENGTH_SHORT).show();
return true;
}
if (id == R.id.search) {
return true;
}
return onOptionsItemSelected(item);
}
public void loadDataBase() {
WorldCountry worldCountry = new WorldCountry(getActivity());
try {
worldCountry.createDatabase();
worldCountry.openDataBase();
Log.d("TAG", "Database open");
} catch (SQLiteException o) {
o.printStackTrace();
Log.d("Tag", o.getMessage());
}
try {
Cursor cursor = worldCountry.QueryData("SELECT name, viewImage FROM country WHERE continent ='آفریقا'");
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
AsiaCountry asiaCountry = new AsiaCountry();
asiaCountry.setName(cursor.getString(0));
asiaCountry.setImageResourceID(cursor.getString(1));
asiaCountries.add(asiaCountry);
} while (cursor.moveToNext());
worldCountry.close();
}
}
} catch (SQLiteException o) {
o.printStackTrace();
Log.d("TAG", o.getMessage());
}
staggeredGridLayoutManager = new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL);
contentAdapter = new ContentAdapter(getActivity(), asiaCountries);
contentAdapter.notifyDataSetChanged();
contentAdapter.setListener(new ContentAdapter.Listener() {
#Override
public void onClick(int position) {
}
});
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(staggeredGridLayoutManager);
recyclerView.setAdapter(contentAdapter);
}
#Override
public boolean onQueryTextSubmit(String query) {
if (contentAdapter != null) {
query = String.valueOf(query.equals(""));
}
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
newText = newText.toLowerCase();
ArrayList<AsiaCountry> asiaCountryArrayList = new ArrayList<>();
for (AsiaCountry asiaCountry : asiaCountries) {
String name = asiaCountry.getName().toLowerCase();
if (name.contains(newText))
asiaCountryArrayList.add(asiaCountry);
}
contentAdapter.setFilter(asiaCountryArrayList);
return true;
}
}
this my adapter.
ContentAdapter
public class ContentAdapter extends RecyclerView.Adapter<ContentAdapter.ViewHolder> {
public Context context;
private List<AsiaCountry> item = Collections.emptyList();
private int mLastPosition = -1;
private Listener listener;
public ContentAdapter(Context context, List<AsiaCountry> item) {
this.context = context;
this.item = item;
}
public void setListener(Listener listener) {
this.listener = listener;
}
#Override
public ContentAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, final int viewType) {
//Defain the view for take layout
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item,
parent, false);
Log.d("Adapter", "Loaded");
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
AsiaCountry asia = item.get(position);
holder.titleNameCountry.setText(asia.getName());
Log.d("TAG", asia.getName());
// String imageFile = asia.getImageResourceID();
holder.titleImageCountry.setImageBitmap(loadBitmapFromAssets(context, asia.getImageResourceID()));
/* Glide.with(context)
.load(loadBitmapFromAssets(context, asia.getImageResourceID()))
.asBitmap()
.into(new SimpleTarget<Bitmap>() {
#Override
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
holder.titleImageCountry.setImageBitmap(resource);
}
});*/
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null) {
listener.onClick(position);
Toast.makeText(context, holder.titleNameCountry.getText().toString() + "is clicked",
Toast.LENGTH_LONG).show();
String nameCountry = holder.titleNameCountry.getText().toString();
Intent intent = new Intent(context, DetialsCountry.class);
intent.putExtra("name", nameCountry);
Log.d("CONT", nameCountry);
context.startActivity(intent);
}
}
});
// When items loading, must be show in animation, for UX better.
if (position > mLastPosition) {
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(
ObjectAnimator.ofFloat(holder.itemView, "translationY",
holder.itemView.getMeasuredHeight() * 2, 0));
ObjectAnimator.ofFloat(holder.itemView, "alpha", 0, 1);
ObjectAnimator.ofFloat(holder.itemView, "scaleX", 0.5f, 1);
ObjectAnimator.ofFloat(holder.itemView, "scaleY", 0.5f, 1);
animatorSet.setInterpolator(new DecelerateInterpolator());
animatorSet.start();
mLastPosition = position;
} else {
ViewHolder.clear(holder.itemView);
}
/* Bitmap photo = BitmapFactory.decodeResource(context.getResources(), asia.getImageResourceID(context));
Palette.from(photo).generate(new Palette.PaletteAsyncListener() {
#Override
public void onGenerated(Palette palette) {
int bgColor = palette.getDarkMutedColor(ContextCompat.getColor(context, android.R.color.black));
holder.titleNameCountry.setBackgroundColor(bgColor);
}
});*/
/* Bitmap photo = BitmapFactory.decodeResource(context.getResources(), country.getTitleCountry(context));
Palette.generateAsync(photo, new Palette.PaletteAsyncListener() {
public void onGenerated(Palette palette) {
int mutedLight = palette.getMutedColor(context.getResources().getColor(android.R.color.black));
holder.titleNameCountry.setBackgroundColor(mutedLight);
}
});*/
}
#Override
public int getItemCount() {
return item.size();
}
//This method take getAssets from assets folder and compare with cursor.getString(1), and show in recyclerview.
#Nullable
private Bitmap loadBitmapFromAssets(Context context, String path) {
InputStream stream = null;
try {
stream = context.getAssets().open(path);
return BitmapFactory.decodeStream(stream);
} catch (Exception ignored) {
} finally {
try {
if (stream != null) {
stream.close();
}
} catch (Exception ignored) {
}
}
return null;
}
public void setFilter(ArrayList<AsiaCountry> arrayList) {
arrayList = new ArrayList<>();
item.addAll(arrayList);
notifyDataSetChanged();
}
public static interface Listener {
public void onClick(int position);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
private ImageView titleImageCountry;
private TextView titleNameCountry;
// Defian the viewHolder
private ViewHolder(View itemView) {
super(itemView);
titleImageCountry = (ImageView) itemView.findViewById(R.id.imageHolder);
titleNameCountry = (TextView) itemView.findViewById(R.id.titleCountry);
}
// public static class ViewHolder {
private static void clear(View itemView) {
ViewCompat.setAlpha(itemView, 1);
ViewCompat.setTranslationY(itemView, 0);
itemView.setPivotY(itemView.getMeasuredHeight() / 2);
ViewCompat.setScaleX(itemView, 1);
ViewCompat.setScaleY(itemView, 1);
ViewCompat.animate(itemView).setInterpolator(null);
Log.d("Animationg", "Loaded");
}
}
}
Please help me :)
In your setFilter in Adapter method, you are again creating object for the parameter you sent, So remove that and made the global item as empty
public void setFilter(ArrayList<AsiaCountry> arrayList) {
//arrayList = new ArrayList<>(); // remove this line
item.clear(); // add this so that it will clear old data
item.addAll(arrayList);
notifyDataSetChanged();
}
To reset the text we should handle in 2 place one is when user press ok, it will call onQueryTextSubmit, second way is user click back arrow at the top, So we should handle both,
#Override
public boolean onQueryTextSubmit(String query) {
// Log.d(TAG, "onQueryTextSubmit() called with: query = [" + query + "]");
if (mAdapter != null)
// reset your complete list here
return true;
}
Second place is,
MenuItemCompat.setOnActionExpandListener(mSearchItem,
new MenuItemCompat.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem menuItem) {
// Log.d(TAG, "onMenuItemActionExpand() called with: menuItem = [" + menuItem + "]");
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem menuItem) {
// Log.d(TAG, "onMenuItemActionCollapse() called with: menuItem = [" + menuItem + "]");
// update your list with complete list
return true;
}
});
Hello am trying to delete an item from my listview am able to delete item from my db but my adapter is not getting updated I have attached the code below`
public class SavedPolygonFragment extends android.support.v4.app.Fragment implements RefreshListener {
private static String LOG_TAG = SavedPolygonFragment.class.getName();
private String message = "No message";
private ListView shapeList;
private TextView textView;
private Button startMainBtn;
private SavedShapeAdapter savedShapeAdapter;
private long shapeId;
private float scaleFactor;
private List<Shape> savedShapes = new ArrayList<>();
private StartDrawingListener startListener;
private DeleteShapesDialog deleteDialog;
public SavedPolygonFragment() {
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
startListener = (StartDrawingListener) activity;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_one, container, false);
savedShapes = getArguments().getParcelableArrayList("shapes");
AssetLog.verbose(LOG_TAG, "savedshapes.size " + savedShapes.size());
shapeList = (ListView) view.findViewById(R.id.shapeList);
textView = (TextView) view.findViewById(R.id.polygonTitle);
startMainBtn = (Button) view.findViewById(R.id.gotoMain);
startMainBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startListener.startMainReceived();
}
});
if (!savedShapes.isEmpty() && !savedShapes.equals(null) && savedShapes.size() != 0) {
textView.setText("Polygons");
shapeList.setVisibility(View.VISIBLE);
startMainBtn.setVisibility(View.GONE);
if (savedShapeAdapter != null) {
savedShapeAdapter.notifyDataSetChanged();
} else {
savedShapeAdapter = new SavedShapeAdapter(savedShapes, getActivity());
shapeList.setAdapter(savedShapeAdapter);
shapeList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
MainActivity_.intent(getActivity())
.savedProjectId(ProjectShapesActivity.projId)
.scaleFactor(ProjectShapesActivity.scaleFactor)
.shapeId(((Shape) view.getTag()).getShapeId())
.lineId(-1)
.pointId(-1)
.start();
}
});
}
}
else{
shapeList.setVisibility(View.GONE);
startMainBtn.setVisibility(View.VISIBLE);
textView.setText("Sorry no shapes are saved");
}
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
registerForContextMenu(shapeList);
}
#Override
public void onRefreshPressed() {
}
#Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo);
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
shapeId = info.id;
menu.add(Menu.NONE, R.id.deleteShapes, Menu.NONE, "Delete");
menu.add(Menu.NONE, R.id.editShapes, Menu.NONE, "Edit");
}
#Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.refresh:
return false;
case R.id.deleteShapes:
if(deleteDialog == null){
Bundle bundle = new Bundle();
bundle.putString("SHAPE", "SHAPE");
bundle.putLong("shapeId", shapeId);
deleteDialog = new DeleteShapesDialog();
deleteDialog.setArguments(bundle);
deleteDialog.show(getActivity().getFragmentManager().beginTransaction(), "showDeleteDialog");
}
return true;
case R.id.editShapes:
return true;
}
return super.onContextItemSelected(item);
}
public void onDataChanged(long shapeid) {
Shape shape;
for (int i = 0; i <savedShapes.size() ; i++) {
shape = savedShapes.get(i);
if(shape.getShapeId() == shapeid){
savedShapes.remove(i);
shapeList.removeViewAt(i);
shapeList.invalidate();
savedShapeAdapter.notifyDataSetChanged();
break;
}
}
}
}
`
Now when user selects yes from deleteDialog i wrote a callback to my activity and in the corresponding methods this is what I do
SavedPolygonFragment polygonFragment = new SavedPolygonFragment();
polygonFragment.onDataChanged(shapeId);
Can somebody show me whats wrong
/////EDIT 1
public void onDataChanged(long shapeid) {
savedShapeAdapter.removeItemById(shapeid);
}
and my adapter
public void removeItemById(long itemId){
for(int i =0; i< shapeList.size() ; i++){
if(shapeList.get(i).getShapeId() == itemId){
shapeList.remove(i);
}
}
notifyDataSetChanged();
}
am able to delete item from my db but my adapter is not getting
updated
Problem is caused by :
savedShapes.remove(i);
line.
Currently removing item from ArrayList which is in SavedPolygonFragment class, not from ArrayList which is used by Adapter to fill ListView.
Using current approach try this way will work by setting new Adapter every time:
if(shape.getShapeId() == shapeid){
savedShapes.remove(i);
savedShapeAdapter = new SavedShapeAdapter(savedShapes, getActivity());
shapeList.setAdapter(savedShapeAdapter);
savedShapeAdapter.notifyDataSetChanged();
break;
}
But this is not optimize solution to create and set new object of Adapter every-time when want to update ListView.
Right approach is create a method in SavedShapeAdapter class for removing item for ArrayList which is used by Adapter and then call it inside onDataChanged method:
public void deleteRowItem(int index){
this.savedShapes.remove(index);
this..notifyDataSetChanged();
}
Now call deleteRowItem when want to delete row item from ListView :
if(shape.getShapeId() == shapeid){
savedShapeAdapter.deleteRowItem(i);
break;
}
I'm writing an application that allows for the sharing of recipes. When one receives a recipe, they can save it to their phone and it will appear as a fragment of a list.
Problem is, when I save it, I get an IllegalStateException for not calling NotifyDataSetChanged(), which I can't find a way to do in the Activity that I am in. If anyone knows how I can find a way to get access to the adapter that calls this, that would be greatly appreciated. Making it static didn't seem to be an option.
public class SmsViewActivity extends Activity {
private static final String TAG = "SmsViewActivity";
private static final String SMS_FOOD = "food_recieved";
private FoodJSONSerializer mSerializer;
public Button mSaveButton, mDismissButton;
public int mNotificationId;
public String message;
private EditText mTitleField;
private EditText mServingsField;
private EditText mDirectionsField;
Food mFood;
private String msg;
private Activity mActivity;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Log.i(TAG, "OnCreate");
mActivity = this;
setContentView(R.layout.sms_view);
mSaveButton = (Button) findViewById(R.id.save_button_sms);
mDismissButton = (Button) findViewById(R.id.dismiss_button_sms);
// ------------------------------------------------------------
// Get extras and display information in view
//String sender = getIntent().getStringExtra("sender");
this.msg = getIntent().getStringExtra("message");
try {
JSONObject jsonRecipe = new JSONObject(this.msg);
this.mFood = new Food(jsonRecipe);
Log.i(TAG, "Food = " + mFood);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// -----------------------------------------------------------------------
mNotificationId = getIntent().getIntExtra("notificationid", 0);
if (mNotificationId == 0) {
Log.e(TAG, "Could not retrieve notification ID.");
Toast.makeText(this, "A fatal error has occurred in SMS viewer.",
Toast.LENGTH_LONG).show();
finish();
}
// Cancel the notification
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager notificationMgr = (NotificationManager) getSystemService(ns);
notificationMgr.cancel(mNotificationId);
// --------------------------------------------------
this.mTitleField = (EditText) findViewById(R.id.food_title_sms);
this.mTitleField.setText(mFood.getTitle());
this.mServingsField = (EditText) findViewById(R.id.food_servings_sms);
this.mServingsField.setText(Integer.toString(mFood.getServings()));
this.mDirectionsField = (EditText) findViewById(R.id.directions_text_sms);
this.mDirectionsField.setText(mFood.getDirections());
// --------------------------------------------------
// Listener for Save button click
this.mSaveButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
FoodStorage.get(mActivity).addFood(mFood);
//NEED TO CALL notifyDataSetChanged(); HERE
finish();
}
});
// Listener for Dismiss button click
this.mDismissButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
backToList();
finish();
}
});
}
public void backToList() {
Intent i = new Intent(this, FoodListActivity.class);
startActivity(i);
}
}
Here is the Fragment where the adapter lives and where every other instance of adding or deleting occurs.
public class FoodListFragment extends ListFragment{
private ArrayList<Food> mFood;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
getActivity().setTitle(R.string.food_title);
mFood = FoodStorage.get(getActivity()).getFood();
FoodAdapter adapter = new FoodAdapter(mFood);
setListAdapter(adapter);
}
#TargetApi(11)
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
View v = super.onCreateView(inflater, parent, savedInstanceState);
ListView listView = (ListView)v.findViewById(android.R.id.list);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
// Use floating context menus on Froyo and Gingerbread
registerForContextMenu(listView);
} else {
// Use contextual action bar on Honeycomb and higher
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
// Required, but not used in this implementation
}
// ActionMode.Callback methods
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.food_list_item_context, menu);
return true;
}
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
// Required, but not used in this implementation
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_delete_food:
FoodAdapter adapter = (FoodAdapter)getListAdapter();
FoodStorage foodStorage = FoodStorage.get(getActivity());
for (int i = adapter.getCount() - 1; i >= 0; i--) {
if (getListView().isItemChecked(i)) {
foodStorage.deleteFood(adapter.getItem(i));
}
}
mode.finish();
adapter.notifyDataSetChanged();
return true;
default:
return false;
}
}
public void onDestroyActionMode(ActionMode mode) {
// Required, but not used in this implementation
}
});
}
return v;
}
public void onListItemClick(ListView l, View v, int position, long id) {
// get the Food from the adapter
Food c = ((FoodAdapter)getListAdapter()).getItem(position);
// start an instance of CrimePagerActivity
Intent i = new Intent(getActivity(), FoodPagerActivity.class);
i.putExtra(FoodFragment.EXTRA_FOOD_ID, c.getId());
startActivityForResult(i, 0);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
((FoodAdapter)getListAdapter()).notifyDataSetChanged();
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.fragment_food_list, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_new_food:
Food food = new Food();
FoodStorage.get(getActivity()).addFood(food);
Intent i = new Intent(getActivity(), FoodPagerActivity.class);
i.putExtra(FoodFragment.EXTRA_FOOD_ID, food.getId());
startActivityForResult(i, 0);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
getActivity().getMenuInflater().inflate(R.menu.food_list_item_context, menu);
}
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo)item.getMenuInfo();
int position = info.position;
FoodAdapter adapter = (FoodAdapter)getListAdapter();
Food food = adapter.getItem(position);
switch (item.getItemId()) {
case R.id.menu_item_delete_food:
FoodStorage.get(getActivity()).deleteFood(food);
adapter.notifyDataSetChanged();
return true;
}
return super.onContextItemSelected(item);
}
private class FoodAdapter extends ArrayAdapter<Food> {
public FoodAdapter(ArrayList<Food> food) {
super(getActivity(), android.R.layout.simple_list_item_1, food);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// if we weren't given a view, inflate one
if (null == convertView) {
convertView = getActivity().getLayoutInflater()
.inflate(R.layout.list_item_food, null);
}
// configure the view for this recipe
Food c = getItem(position);
TextView titleTextView =
(TextView)convertView.findViewById(R.id.food_list_item_titleTextView);
titleTextView.setText(c.getTitle());
TextView servingsTextView =
(TextView)convertView.findViewById(R.id.food_list_item_servingsTextView);
servingsTextView.setText("Makes " + c.getServings() + " servings");
TextView ingredientsTextView = (TextView) convertView
.findViewById(R.id.food_list_item_ingredientsTextView);
JSONArray j = c.jIngredients;
String display = "";
for (int i = 0; i < j.length(); i++) {
try {
display = display + j.get(i) + "\n";
} catch (JSONException e) {
// Do nothing.
e.printStackTrace();
}
}
ingredientsTextView.setText("Ingredients:\n" + display);
TextView directionsTextView =
(TextView)convertView.findViewById(R.id.food_list_item_directionsTextView);
directionsTextView.setText("Directions:\n " + c.getDirections());
return convertView;
}
}
}
You may use Eventbus from greenrobot. It provides you with a way to post events anywhere to any subscriber who can receive the event and call any method.
In the onCreate method of your fragment, call this EventBus.getDefault().register(this); to register your fragment as a subscriber.
Create a new method in your fragment: public void onEvent(AnyEventType event) {}. When an event is posted on the event bus, this method will be called. you may call adapter.notifyDatasetChanged() in the onEvent method. AnyEventType can be just any class (can be a POJO). You may use this class to pass any info to your fragment.
In your activity, you can call EventBus.getDefault().post(event); to notify your fragment. The onEvent method in your fragment will be executed when the event is posted.
Refer to the EventBus readme for more info.
I apologize for the awkward wording of my title, I'm not sure how to succinctly ask this question. I have a listView within a fragment called TaskListFragment. This fragment is started after a user selects a course from CourseListFragment, and it shows a list of tasks for that course. From here, the user can add a task. Upon saving that task, they are brought back to TaskListFragment, where the task does not appear. If you navigate up to get back to CourseListFragment and then select the course again, the task appears in the list. Likewise if I try to delete a task, it still shows in the list until I navigate up and go back again. Any idea why this might be happening?
Below is my TaskListFragment:
public class TaskListFragment extends ListFragment {
private ArrayList<Task> mTasks;
private static String courseName;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
setHasOptionsMenu(true);
courseName = getActivity().getIntent().getStringExtra("name");
getActivity().setTitle(courseName);
ArrayList<Task> alltasks = TaskLab.get(getActivity()).getTasks();
mTasks = filterTasks(alltasks);
TaskAdapter adapter = new TaskAdapter(mTasks);
setListAdapter(adapter);
adapter.notifyDataSetChanged();
}
private ArrayList<Task> filterTasks(ArrayList<Task> tasks) {
ArrayList<Task> filteredTasks = new ArrayList<Task>();
for (Task t: tasks) {
if (t.getBelongsToCourse().equals(courseName)) {
filteredTasks.add(t);
}
}
return filteredTasks;
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
//Get the Task from the adapter
Task t = ((TaskAdapter)getListAdapter()).getItem(position);
// Start TaskActivity for this task
Intent i = new Intent(getActivity(), TaskActivity.class);
i.putExtra(TaskFragment.EXTRA_TASK_ID, t.getId());
startActivity(i);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.fragment_task_list, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_new_task:
Task task = new Task();
task.setBelongsToCourse(courseName);
TaskLab.get(getActivity()).addTask(task);
Intent i = new Intent(getActivity(), TaskActivity.class);
i.putExtra(TaskFragment.EXTRA_TASK_ID, task.getId());
startActivityForResult(i, 0);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
getActivity().getMenuInflater().inflate(R.menu.task_list_item_context, menu);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
View v = super.onCreateView(inflater, parent, savedInstanceState);
ListView listView = (ListView)v.findViewById(android.R.id.list);
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
// Required, but not used in this implementation
}
// ActionMode.Callback methods
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.task_list_item_context, menu);
return true;
}
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
// Required, but not used in this implementation
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_delete_task:
TaskAdapter adapter = (TaskAdapter)getListAdapter();
TaskLab taskLab = TaskLab.get(getActivity());
for (int i = adapter.getCount() - 1; i >= 0; i--) {
if (getListView().isItemChecked(i)) {
taskLab.deleteTask(adapter.getItem(i));
}
}
mode.finish();
adapter.notifyDataSetChanged();
return true;
default:
return false;
}
}
public void onDestroyActionMode(ActionMode mode) {
// Required, but not used in this implementation
}
});
return v;
}
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo)item.getMenuInfo();
int position = info.position;
TaskAdapter adapter = (TaskAdapter)getListAdapter();
Task task = adapter.getItem(position);
switch (item.getItemId()) {
case R.id.menu_item_delete_task:
TaskLab.get(getActivity()).deleteTask(task);
adapter.notifyDataSetChanged();
return true;
}
return super.onContextItemSelected(item);
}
#Override
public void onResume() {
super.onResume();
((TaskAdapter)getListAdapter()).notifyDataSetChanged();
}
private class TaskAdapter extends ArrayAdapter<Task> {
public TaskAdapter(ArrayList<Task> tasks) {
super(getActivity(), 0, tasks);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// If we weren't given a view, inflate one
if (convertView == null) {
convertView = getActivity().getLayoutInflater()
.inflate(R.layout.list_item_task, null);
}
// Configure the view for this Task
Task t = getItem(position);
TextView titleTextView =
(TextView)convertView.findViewById(R.id.task_list_item_titleTextView);
titleTextView.setText(t.getTitle());
TextView dateTextView =
(TextView)convertView.findViewById(R.id.task_list_item_dateTextView);
dateTextView.setText(t.getDate().toString());
CheckBox completedCheckBox =
(CheckBox)convertView.findViewById(R.id.task_list_item_completedCheckBox);
completedCheckBox.setChecked(t.isCompleted());
return convertView;
}
}
}
EDIT: Below is my TaskLab, which is used to add and delete tasks.
public class TaskLab {
private static final String TAG = "TaskLab";
private static final String FILENAME = "tasks.json";
private ArrayList<Task> mTasks;
private TaskJSONSerializer mSerializer;
private static TaskLab sTaskLab;
private Context mAppContext;
private TaskLab(Context appContext) {
mAppContext = appContext;
mSerializer = new TaskJSONSerializer(mAppContext, FILENAME);
try {
mTasks = mSerializer.loadTasks();
} catch (Exception e) {
mTasks = new ArrayList<Task>();
Log.e(TAG, "Error loading tasks: ", e);
}
}
public static TaskLab get(Context c) {
if (sTaskLab == null) {
sTaskLab = new TaskLab(c.getApplicationContext());
}
return sTaskLab;
}
public void addTask(Task t) {
mTasks.add(t);
}
public void deleteTask(Task t) {
mTasks.remove(t);
}
public boolean saveTasks() {
try {
mSerializer.saveTasks(mTasks);
Log.d(TAG, "Tasks saved to file");
return true;
} catch (Exception e) {
Log.e(TAG, "Error saving tasks: ", e);
return false;
}
}
public ArrayList<Task> getTasks() {
return mTasks;
}
public Task getTask(UUID id) {
for (Task t : mTasks) {
if (t.getId().equals(id)) {
return t;
}
} return null;
}
}