2016-02-17 52 views
0

我有一個RecyclerView,點擊時會啓動一個新的Activity(長按和短按)。當我點擊它時,相應的動作正在進行3次(有時是2次),無論如何,當我只需要執行一次時,它正在被多次執行。有一個線程處理這些動作,但該線程只執行一次。Recycler View onClick被多次調用?

一個快速運行直通的順序是:

  1. recyclerview被加載,用戶可以長按或快速點擊列表中的一個項目。
  2. 快速點擊調用openConversation()方法,將推出一項新的活動(在目前的版本,它推出的活動很多次,因爲活動堆棧有啓動的活動2-3實例)
  3. 或者如果布爾條件發起活動openConversation()是假的吐司消息發送(在這個bug中吐司顯示從我的測試中3次)
  4. 像長期按下推出的活動啓動2-3次,當它只應該啓動一次,因爲活動堆棧上有多個實例

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); 
    } 
} 

回答

4

我認爲您的活動正在被解僱3次,因爲您的RecyclerView每次都會打電話給.addOnItemTouchListener(),這會每次都會添加一個新的聽衆。

您的方法eventListClickListener()只能在您的onCreate()中調用一次,而不是每次都在您的updateEventsHard()updateEventsSoft()中調用。

+0

非常感謝它的工作! –