Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recycler View onClick being called multiple times?

I have a RecyclerView that launches a new Activity when it is clicked (both long press and short). When I click it the corresponding action is being done 3 times (sometimes 2) in any case it is being done multiple times when I only want it done once. There is a thread that handles these actions but that thread is only executed once.

A quick run thru of the sequence is:

  1. recyclerview is loaded, user can long press or quick click an item on the list.
  2. A quick click calls a openConversation() method which will launch a new activity(in the current version it launches the activity many times because the activity stack has 2-3 instances of the launched activity)
  3. Or if the boolean condition to launch the activity in openConversation() is false a toast message is sent (in this bug the toast is displayed 3 times from my tests)
  4. Like wise on a long press the launched activity is launched 2-3 times when it should only be launched once, because there is more than one instance on the activity stack

public class EventListActivity extends AppCompatActivity implements 
NavigationView.OnNavigationItemSelectedListener {

    private static final int VIBRATE_MILLISECONDS = 50;
    private static final int REFRESH_ANI_MILLIS = 2500;
    final Handler handler = new Handler();
    private Context applicationContext;
    private List<ParseObject> eventList;
    final Runnable updateEventsHard = new Runnable() {
        @Override
        public void run() {
            updateEventCards(true);
        }
    };

    final Runnable updateEventsSoft = new Runnable() {
        @Override
        public void run() {
            updateEventCards(false);
        }
    };

    final Runnable initSwipeRefresh = new Runnable() {
        @Override
        public void run() {
            initSwipeRefresh();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_event_list);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        applicationContext = getApplicationContext();

        handler.post(updateEventsHard);

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
        View headerLayout = navigationView.inflateHeaderView(R.layout.nav_header_event_list);
        TextView headerUsername = (TextView) headerLayout.findViewById(R.id.drawer_username);
        headerUsername.setText(CurrentActiveUser.getInstance().getUsername());

        handler.post(initSwipeRefresh);
    }

    private void initSwipeRefresh() {
        final SwipeRefreshLayout swipeView = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
        swipeView.setColorSchemeResources(android.R.color.holo_blue_dark, android.R.color.holo_blue_light, android.R.color.holo_green_light, android.R.color.holo_green_light);
        swipeView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                swipeView.setRefreshing(true);
                (new Handler()).postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        updateEventCards(true);
                        swipeView.setRefreshing(false);
                    }
                }, REFRESH_ANI_MILLIS);
            }
        });
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();
        switch (id) {
            case (R.id.nav_my_profile):
                Dialog.makeDialog(EventListActivity.this, getString(R.string.upcoming),
                        getString(R.string.profile_upcoming));
                break;
            case (R.id.nav_logout):
                CurrentActiveUser.getInstance().logout();
                Intent intent = new Intent(applicationContext, LoginActivity.class);
                startActivity(intent);
                finish();
                break;
            case (R.id.nav_share):
                Intent share = new Intent(Intent.ACTION_SEND);
                share.setType(StringResources.PLAIN_CONTENT_TYPE);
                share.putExtra(Intent.EXTRA_TEXT, R.string.app_share);
                startActivity(Intent.createChooser(share, getString(R.string.app_share_title)));
                break;
            case (R.id.nav_about):
                Intent aboutIntent = new Intent(applicationContext, AboutActivity.class);
                startActivity(aboutIntent);
                break;
            case (R.id.nav_legal):
                Intent legalIntent = new Intent(applicationContext, LegalActivity.class);
                startActivity(legalIntent);
                break;
        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    //display clickable a list of all users
    @SuppressWarnings("unchecked")
    private void updateEventCards(Boolean hard) {
        ArrayList<EventObject> eventObjects = new ArrayList<>();
        if (NetworkState.isConnected(applicationContext)) {
            Query<ParseObject> query = new Query<>(Events.class);
            query.orderByASC(Events.START_TIME);
            if (hard) {
                eventList = query.executeHard();
            } else {
                eventList = query.execute();
            }
            ParseObject current;
            if (eventList != null) {
                if (eventList.size() > 0) {
                    for (int i = 0; i < eventList.size(); i++) {
                        current = eventList.get(i);
                        eventObjects.add(
                                new EventObject(
                                        current.getString(Events.NAME),
                                        current.getString(Events.LOCATION),
                                        current.getLong(Events.START_TIME),
                                        current.getLong(Events.END_TIME),
                                        current.getString(Events.IMAGE)
                                )
                        );
                    }
                } else {
                    Dialog.makeToast(applicationContext, getString(R.string.no_events));
                }
            } else {
                Dialog.makeToast(applicationContext, getString(R.string.error_loading_events));
            }
        } else {
            Dialog.makeToast(applicationContext, getString(R.string.no_network));
        }
        attachToEventListAdapter(eventObjects);
    }

    private void attachToEventListAdapter(ArrayList<EventObject> eventObjects) {
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(applicationContext));
        eventListClickListener(recyclerView);
        EventListAdapter mAdapter = new EventListAdapter(eventObjects, applicationContext);
        recyclerView.setAdapter(mAdapter);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
    }

    private synchronized void eventListClickListener(RecyclerView recyclerView) {
        recyclerView.addOnItemTouchListener(
                new RecyclerItemClickListener(
                        EventListActivity.this, recyclerView,
                        new RecyclerItemClickListener.OnItemClickListener() {
                            @Override
                            public void onItemClick(View view, int position) {
                                Log.d("Click", "Quick");
                                openConversation(eventList.get(position));
                            }

                            @Override
                            public void onItemLongClick(View view, int position) {
                                Vibrator vibe = (Vibrator) applicationContext.getSystemService(Context.VIBRATOR_SERVICE);
                                vibe.vibrate(VIBRATE_MILLISECONDS);
                                openEventInfo(eventList.get(position));
                            }
                        }));
    }

    private void openConversation(ParseObject event) {
        Live status = DateVerifier.goLive(event.getLong(Events.START_TIME), event.getLong(Events.END_TIME));
        if (status.goLive()) {
            Intent intent = new Intent(applicationContext, MessagingActivity.class);
            intent.putExtra(IntentKeys.EVENT_ID, event.getObjectId());
            intent.putExtra(IntentKeys.EVENT_NAME, event.getString(Events.NAME));
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(intent);
        } else {
            Dialog.makeToast(applicationContext, String.valueOf(System.currentTimeMillis() % 1000));
        }
    }

    private void openEventInfo(ParseObject event) {
        Intent intent = new Intent(applicationContext, EventInfoActivity.class);
        intent.putExtra(IntentKeys.EVENT_NAME, event.getString(Events.NAME));
        intent.putExtra(IntentKeys.EVENT_INFO, event.getString(Events.INFO));
        intent.putExtra(IntentKeys.EVENT_CARD, event.getString(Events.MATCH_CARD));
        intent.putExtra(IntentKeys.EVENT_IMAGE, event.getString(Events.IMAGE));
        intent.putExtra(IntentKeys.EVENT_START_TIME, event.getLong(Events.START_TIME));
        intent.putExtra(IntentKeys.EVENT_LOCATION, event.getString(Events.LOCATION));
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(intent);
    }

    public void onStart(){
        super.onStart();
        handler.post(updateEventsSoft);
    }

    public void onResume() {
        super.onResume();
        handler.post(updateEventsSoft);
    }
}
like image 372
Austin Park Avatar asked Dec 24 '22 09:12

Austin Park


1 Answers

I think your events are being fired 3 times because every time on your RecyclerView you are calling .addOnItemTouchListener() which will add a new listener every time.

Your method eventListClickListener() should only be called once in your onCreate(), not every time in your updateEventsHard() or updateEventsSoft().

like image 159
riggaroo Avatar answered Jan 07 '23 09:01

riggaroo