Search code examples
androidandroid-recyclerviewonbackpressedandroid-search

Unable to go to previous activity-current activity shows up multiple times


I've 2 activities. MainActivity has a list of notes & secondActivity individually displays them. The problem is when I click on one of the notes from MainActivity, it goes to secondActivity, but when I click the back button, secondActivity opens up. After 4-5 tries, I reach the MainActivity. The navigation was working fine, but I don't how all of a sudden it's breaking.

MainActivity:

  public class MainActivity extends AppCompatActivity{

        private StaggeredGridLayoutManager gridLayoutManager;
        private RecyclerView recyclerView;
         private List<Note> noteList, multiSelectList, filteredList;
        public  NotesAdapter notesAdapter;
        private Notedatabase notedatabase;
        private String TAG = MainActivity.class.getSimpleName();
        private FloatingActionButton maddbtn;
        private int position;
        private SearchView mSearchView;
        private boolean isMultiSelect = false;
        private Menu context_menu;
        private ActionMode mActionMode;
        private CoordinatorLayout mCoordinatorLayout;
        private RelativeLayout mEmptyContainer;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            initViews();
            displayList();

    /*

            notesList.addAll(noteList);

            List<Note> notesList = getNotes();
            notesAdapter = new NotesAdapter(notesList,MainActivity.this);
            recyclerView.setAdapter(notesAdapter);
            */
        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.menu,menu);

          // Searchable config with searchview
            SearchManager manager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
            mSearchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
            mSearchView.setSearchableInfo(manager.getSearchableInfo(getComponentName()));

            mSearchView.setMaxWidth(Integer.MAX_VALUE);


            // Set Listener
            mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
                @Override
                public boolean onQueryTextSubmit(String query) {
                    // filter when query is submitted
                    Log.d(TAG, "onQueryTextSubmit: " + query);
                filteredList = filter(newText, noteList);
                notesAdapter.filterList(filteredList);
                if (filteredList.isEmpty()) displayEmptyState();
                    return false;
                }

                @Override
                public boolean onQueryTextChange(String newText) {
                    // filter progressively as query changes
                    Log.d(TAG, "onQueryTextChange: " + newText);
                    if(!newText.isEmpty() && mEmptyContainer.getVisibility() == View.VISIBLE) 
                        mEmptyContainer.setVisibility(View.GONE);


                    if(newText.isEmpty() && mEmptyContainer.getVisibility() == View.VISIBLE) {
                        Log.d(TAG, "Empty query");
                        mEmptyContainer.setVisibility(View.GONE);
                        // Close the keyboard
                        mSearchView.post(new Runnable() {
                            @Override
                            public void run() {
                            mSearchView.clearFocus();
                            if(!mSearchView.isIconified())
                                mSearchView.setIconified(true);
                            }
                        });
                    }
                filteredList = filter(newText, noteList);
                notesAdapter.filterList(filteredList);
                if (filteredList.isEmpty()) displayEmptyState();    
                    return false;
                }
            });

            mSearchView.setOnCloseListener(new SearchView.OnCloseListener() {
                @Override
                public boolean onClose() {
                    if(mEmptyContainer.getVisibility() == View.VISIBLE) mEmptyContainer.setVisibility(View.GONE);
                    return false;
                }
            });

            return true;
        }


        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            if(item.getItemId() == R.id.action_search) {
                // search action
                return true;
            }

            return super.onOptionsItemSelected(item);
        }

        @Override
        public void onBackPressed() {
            // close searchview
            if(!mSearchView.isIconified()) {
                // Clears the text
                mSearchView.setIconified(true);
                mSearchView.onActionViewCollapsed();
                refreshAdapter();
                if(mEmptyContainer.getVisibility() == View.VISIBLE) mEmptyContainer.setVisibility(View.GONE);

            }
            else super.onBackPressed();
        }

        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            if(requestCode == REQUEST_CODE) {
                if (resultCode == 1) {
                    Log.d(TAG, "Request code is 1");
                    noteList.add((Note) data.getSerializableExtra("note"));
                    notesAdapter.notifyDataSetChanged();
                    //displayList();
                }
                else if(resultCode == 2) {
                    Log.d(TAG, "Request code 2, update return");
                    noteList.set(position, (Note) data.getSerializableExtra("note"));
                    notesAdapter.notifyDataSetChanged();
                }
                else if(resultCode == 3) {
                    Log.d(TAG, "Request code 3, delete return");
                    Log.d(TAG, "Deleting this from list:" + (Note) data.getSerializableExtra("note"));
                    noteList.remove(MainActivity.this.position);
                    notesAdapter.notifyItemRemoved(MainActivity.this.position);
                    if(noteList.isEmpty()) displayEmptyState();
                }
            }
        }

        private void displayList() {
        notedatabase = Notedatabase.getInstance(MainActivity.this);
        new RetrieveTask(this).execute();
        }

        private void initViews() {
            recyclerView = findViewById(R.id.recyclerview);
            gridLayoutManager = new StaggeredGridLayoutManager(2,1);
            mCoordinatorLayout = findViewById(R.id.coordinatorLayout);

            mEmptyContainer = findViewById(R.id.empty_container);

            recyclerView.setLayoutManager(gridLayoutManager);

            noteList = new ArrayList<>();
            multiSelectList = new ArrayList<>();

            notesAdapter = new NotesAdapter(noteList,MainActivity.this,multiSelectList);
            recyclerView.setAdapter(notesAdapter);

            maddbtn = findViewById(R.id.add_fab);
            maddbtn.setOnClickListener(v -> {
                Intent intent = new Intent(MainActivity.this,NoteActivity.class);
                startActivityForResult(intent,REQUEST_CODE);
            });
        }

    /*
        @Override
        public void onClick(View view, int pos) {

            Log.d(TAG, "Recylerview item onClick: ");
            MainActivity.this.position  = pos;
            Intent intent = new Intent(MainActivity.this,NoteActivity.class);
            intent.putExtra("note",noteList.get(position));
            Log.d(TAG, "list.get(position): " + noteList.get(pos).getDesc());
            startActivityForResult(intent,REQUEST_CODE);

        }
    */
     /*   @Override
        public void onClick(Note note) {

            Log.d(TAG, "onClick with args as note1");
            Intent intent = new Intent(MainActivity.this,NoteActivity.class);
            intent.putExtra("note",note);
            startActivityForResult(intent,REQUEST_CODE);
        }
    */
         /*
        @Override
        public void onLongClick(View view, int pos) {
        Log.d(TAG, "onLongClick ");
            if(!isMultiSelect) {
                multiSelectList = new ArrayList<Note>();
                isMultiSelect = true;

                if(mActionMode == null) {
                    mActionMode = startActionMode(mActionModeCallback);
                }
            }

            multi_select(pos);
        }
    */
        private void multi_select(int pos) {
            if(mActionMode != null) {
                if(multiSelectList.contains(noteList.get(pos))) {
                    Log.d(TAG, "multi_select removed: " + multiSelectList.contains(noteList.get(pos)));
                    multiSelectList.remove(noteList.get(pos));
                }
                else {
                    Log.d(TAG, "multi_select added: " + multiSelectList.contains(noteList.get(pos)));
                    multiSelectList.add(noteList.get(pos));
                }

                if(multiSelectList.size() > 0) mActionMode.setTitle("" + multiSelectList.size() + " selected");
                else mActionMode.setTitle("");
                refreshAdapter();
            }
        }

        private void refreshAdapter() {
        notesAdapter.selectednotes_list = multiSelectList;
        notesAdapter.list = noteList;
        notesAdapter.notifyDataSetChanged();
        }


        class RetrieveTask extends AsyncTask<Void,Void,List<Note>>{
            private WeakReference<MainActivity> weakReference;

            public RetrieveTask(MainActivity mainActivity) {
            weakReference = new WeakReference<>(mainActivity);
            }

            @Override
            protected List<Note> doInBackground(Void... voids) {
                if(weakReference.get()!=null)
                    return weakReference.get().notedatabase.getNoteDao().getNotes();
                else
                return null;
            }

            @Override
            protected void onPostExecute(List<Note> notes) {
                if(notes!=null & notes.size()>0) {
                    if(mEmptyContainer.getVisibility() == View.VISIBLE) mEmptyContainer.setVisibility(View.GONE);
                    weakReference.get().noteList = notes;
                    weakReference.get().filteredList = noteList;

//weakReference.get().noteList.addAll(weakReference.get().getNotes());
                    Log.d(TAG, "Result: " + notes);
                    weakReference.get().notesAdapter = new NotesAdapter(notes,weakReference.get(),multiSelectList);
    /*
                    // Randomly set note background
                    for(Note n:notes) {
                        n.setColor(getRandomMaterialColor(MainActivity.this,"500"));
                    }

    */              weakReference.get().recyclerView.addOnItemTouchListener(new RecyclerTouchListener(recyclerView, getApplicationContext(), new ClickListener() {
                        @Override
                        public void onClick(View view, int pos) {
                            if (isMultiSelect)
                                multi_select(pos);
                            else {
                                Log.d(TAG, "Recylerview item onClick: ");
                                MainActivity.this.position = pos;
                                Intent intent = new Intent(MainActivity.this, NoteActivity.class);
                              intent.putExtra("note",filteredList.get(pos).get(pos));
                                Log.d(TAG, "pos: " + pos);
                                Log.d(TAG, "list.get(position): " + weakReference.get().filteredList.get(pos).get(position).getDesc());
                                startActivityForResult(intent, REQUEST_CODE);
                            }
                        }

                        @Override
                        public void onClick(View view) {
                            Log.d(TAG, "onClick with args as note");
                            Intent intent = new Intent(MainActivity.this, NoteActivity.class);
                            intent.putExtra("note", noteList.get(recyclerView.getChildAdapterPosition(view)));
                            startActivityForResult(intent, REQUEST_CODE);
                        }

                        @Override
                        public void onLongClick(View view, int pos) {
                            Log.d(TAG, "onLongClick ");
                            if(!isMultiSelect) {
                                multiSelectList = new ArrayList<Note>();
                                isMultiSelect = true;

                                if(mActionMode == null) {
                                    mActionMode = startActionMode(mActionModeCallback);
                                }
                            }

                            multi_select(pos);
                        }
                    }));

                    weakReference.get().recyclerView.setAdapter(weakReference.get().notesAdapter);
                    weakReference.get().notesAdapter.notifyDataSetChanged();
                }
                else{
                    // empty state
                    displayEmptyState();
                }
            }
        }

        private void displayEmptyState() {
            mEmptyContainer.setVisibility(View.VISIBLE);
        }

        private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
            @Override
            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                //Prepare the menu
                MenuInflater inflater = mode.getMenuInflater();
                inflater.inflate(R.menu.contextual_action,menu);
                context_menu = menu;
                return true;
            }

            @Override
            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                //mode.getCustomView().setBackgroundColor(getApplicationContext().getResources().getColor(android.R.color.white));
                return false;
            }

            @Override
            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.action_delete:
                            // display alert dialog
                            AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);

                            builder.setMessage("Delete " + multiSelectList.size() + " notes?");
                            builder.setCancelable(true);
                            builder.setPositiveButton(R.string.alert_yes,(dialog, which) -> {
                                // Deleting notes
                                for (int i = 0; i < multiSelectList.size(); i++) {
                                    Log.d(TAG, "Deleting: " + multiSelectList.get(i));
                                    notedatabase.getNoteDao().deleteNotes(multiSelectList.get(i));
                                    noteList.remove(multiSelectList.get(i));
                                }
                                // Display Snackbar
                                displaySnackbar(mCoordinatorLayout,R.string.delete_success);
                                dialog.cancel();
                                // Refresh adapter
                                refreshAdapter();
                                // dismiss the contextual action bar
                                if(mActionMode!=null) mActionMode.finish();
                                // check for empty state
                                if(noteList.isEmpty()) displayEmptyState();
                            });

                            builder.setNegativeButton(R.string.alert_no,(dialog, which) -> {
                                dialog.cancel();
                                if(mActionMode!=null) mActionMode.finish();
                            });

                            builder.setOnCancelListener(dialog1 -> {
                                Log.d(TAG, "onCancelListener: ");
                                if(mActionMode!=null) mActionMode.finish();
                            });

                        AlertDialog dialog = builder.create();
                            dialog.show();


                   return true;

                default:
                    return false;
                }
            }

            @Override
            public void onDestroyActionMode(ActionMode mode) {
                mActionMode = null;
                isMultiSelect = false;
                multiSelectList = new ArrayList<Note>();
                refreshAdapter();
            }
        };

        @Override
        protected void onDestroy() {
            notedatabase.cleanUp();
            super.onDestroy();
        }

    }

SecondActivity:

public class NoteActivity extends AppCompatActivity {
EditText mtext;
//FloatingActionButton mfab;
OptionsFabLayout fab_menu;
CoordinatorLayout mCoordinatorLayout;
private String TAG = NoteActivity.class.getSimpleName();
private NoteDao note_dao; // Sql access object
private Note temp_note; //Used for creating a note
public Notedatabase notedatabase;
private boolean update = false;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_note);

        mtext =  findViewById(R.id.note_text);
        fab_menu =  findViewById(R.id.fab);

        mCoordinatorLayout= findViewById(R.id.coordinatorLayout);

        notedatabase = Notedatabase.getInstance(NoteActivity.this);

        if((temp_note = (Note)getIntent().getSerializableExtra("note"))!=null) {
            update = true;
            mtext.setText(temp_note.getDesc());
        }


        fab_menu.setMainFabOnClickListener( v -> {
            if(fab_menu.isOptionsMenuOpened()) fab_menu.closeOptionsMenu();
        });


        fab_menu.setMiniFabSelectedListener(fabItem -> {

            switch(fabItem.getItemId()) {

                case R.id.fab_save:
                    // Call update method of DAO
                    if (update) {
                        temp_note.setDesc(mtext.getText().toString());
                        temp_note.setTime(getDate());
                        notedatabase.getNoteDao().Update(temp_note);
                        setResult(temp_note, 2);
                    } else {
                        // Insert
                        if (TextUtils.isEmpty(mtext.getText().toString())) {
                            displaySnackbar(mCoordinatorLayout, R.string.empty_insert);
                        } else {
                            temp_note = new Note(mtext.getText().toString(), getDate());
                            Log.d(TAG, "Inserting values as : " + temp_note.getId() + temp_note.getDesc() + temp_note.getTime());
                            new InsertTask(NoteActivity.this, temp_note).execute();
                        }
                    }
                    break;

                case R.id.fab_delete:
                    // Delete
                    if(TextUtils.isEmpty(mtext.getText().toString())) {
                        displaySnackbar(mCoordinatorLayout,R.string.empty_insert);
                    }
                    if ((temp_note = (Note) getIntent().getSerializableExtra("note")) != null) {
                        displayAlert(NoteActivity.this, temp_note);
                    }
                    break;

                case R.id.fab_share:
                    // Share
                    getShareIntent(NoteActivity.this, temp_note);
                    break;
            }
        });
    }

    public void displayAlert(Context context, Note note) {
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setMessage(R.string.alert_message);
        builder.setCancelable(true);
        builder.setPositiveButton(R.string.alert_yes,(dialog, which) -> {
            // Delete note
                Log.d(TAG, "Deleting values :" + note.getDesc() + note.getTime());
                notedatabase.getNoteDao().delete(note);
                displaySnackbar(mCoordinatorLayout,R.string.delete_success);
                setResult(note, 3);
                dialog.cancel();
        });

        builder.setNegativeButton(R.string.alert_no,(dialog, which) -> {
            dialog.cancel();
        });

        AlertDialog dialog = builder.create();
        dialog.show();
    }


    @Override
    public void onBackPressed() {
       if(fab_menu.isOptionsMenuOpened())  fab_menu.closeOptionsMenu();
       super.onBackPressed();

    }

public void setResult(Note note, int flag) {
        setResult(flag , new Intent().putExtra("note",note));
        finish();
}

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(resultCode==1) {
                Snackbar.make(mCoordinatorLayout,R.string.success_insert,Snackbar.LENGTH_SHORT).show();
        }
        else
            Snackbar.make(mCoordinatorLayout,R.string.failure_insert,Snackbar.LENGTH_SHORT).show();
    }
}

Solution

  • I think I've solved it. The thing was AFAIK, I was storing the list of filter in original list, noteList. I've added a new list filteredList, initialised as noteList but stores the result of filter. As a result, now I don't need to call displayList() everytime I go back to original state. Also, earlier whenever I used to backspace a char, it won't show me increased result, now that too is fine. Updated the code as per changes