We have a ReciclerView , a list is displayed on the screen. The list is updated every 5 seconds. When you click on a list item, the item expands (to display more information) or narrows back.

enter image description here

The problem is that the open element is narrowed down because the timer is running.

I need to stop the timer when expanding the element ( handler or runnable or as it is correctly called there), and when it is narrowed, start it again. For this, I wrote 2 methods in MainActivity - startRepeatingTask() and stopRepeatingTask() , but I don’t know how to access them from the ViewHolder class.

MainActivity.java

 public class MainActivity extends AppCompatActivity { RecyclerView recyclerView; RecyclerView.LayoutManager layoutManager; ConnectionItemAdapter adapter; List<ConnectionItem> connectionItems; Handler timerHandler; Runnable timerRunnable; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); InitRecyclerView(); timerHandler = new Handler(); timerRunnable = new Runnable() { @Override public void run() { //тут обновляется адаптер adapter.notifyDataSetChanged(); timerHandler.postDelayed(this, 5000); //каждые 5 секунд } }; timerHandler.postDelayed(timerRunnable, 5000); } void startRepeatingTask() { timerRunnable.run(); } void stopRepeatingTask() { timerHandler.removeCallbacks(timerRunnable); } } 

ViewHolder.java

 public class ConnectionItemsAdapterViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { private boolean isViewExpanded = false; private int originalHeight = 0; public ConnectionItemsAdapterViewHolder(View itemView) { super(itemView); itemView.setOnClickListener(this); fcuName = (TextView)itemView.findViewById(R.id.FcuName); branchName = (TextView) itemView.findViewById(R.id.FcuBranchName); result = (TextView) itemView.findViewById(R.id.ResultText); versionIcon = (ImageView) itemView.findViewById(R.id.versionIcon); // If isViewExpanded == false then set the visibility // of whatever will be in the expanded to GONE if (isViewExpanded == false) { // Set Views to View.GONE and .setEnabled(false) branchName.setVisibility(View.GONE); branchName.setEnabled(false); } } public TextView fcuName; public TextView branchName; public ImageView versionIcon; public TextView result; @Override public void onClick(final View view) { // If the originalHeight is 0 then find the height of the View being used // This would be the height of the cardview if (originalHeight == 0) { originalHeight = view.getHeight(); } // Declare a ValueAnimator object ValueAnimator valueAnimator; if (!isViewExpanded) { branchName.setVisibility(View.VISIBLE); branchName.setEnabled(true); isViewExpanded = true; // Вот где-то тут надо остановить таймер valueAnimator = ValueAnimator.ofInt(originalHeight, originalHeight + (int) (originalHeight * 2.0)); // These values in this method can be changed to expand however much you like } else { isViewExpanded = false; valueAnimator = ValueAnimator.ofInt(originalHeight + (int) (originalHeight * 2.0), originalHeight); Animation a = new AlphaAnimation(1.00f, 0.00f); // Fade out a.setDuration(200); // Set a listener to the animation and configure onAnimationEnd a.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { branchName.setVisibility(View.INVISIBLE); branchName.setEnabled(false); } @Override public void onAnimationRepeat(Animation animation) { } }); // Set the animation on the custom view branchName.startAnimation(a); } valueAnimator.setDuration(200); valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { Integer value = (Integer) animation.getAnimatedValue(); view.getLayoutParams().height = value.intValue(); view.requestLayout(); } }); valueAnimator.start(); } } 

Just started to learn android and java, maybe someone will tell a more correct approach.

  • write a ViewHolder in the same class where RecyclerView initialized (MainActivity same?), and contact as usual: startRepeatingTask() - Jarvis_J

2 answers 2

The correct way is to push the interface through the adapter in the ViewHolder.

  1. We create the interface
 public interface MyInterface { void onClick(); } 
  1. Pass it to the adapter's constructor and initialize the link to it in the adapter:
 public class MyAdapter extends .... { private MyInterface mMyInterface; public MyAdapter(MyInterface myInterface) { mMyInterface = myInterface; } } 
  1. Pass it also to the ViewHolder when creating it
 public class ConnectionItemsAdapterViewHolder extends RecyclerView.ViewHolder { private MyInterface mMyInterface; public ConnectionItemsAdapterViewHolder(View itemView, MyInterface mMyInterface) { super(itemView); mMyInterface = myInterface; } } 
  1. At the right moment, call his method:
 @Override public void onClick(final View view) { mMyInterface.onClick(); } 
  1. When creating an adapter in activation, transfer the interface implementation:
 MyAdapter adapter = new MyAdapter(new MyInterface(){ @Override public void onClick(){ startRepeatingTask(); } }) 

And the easiest way is to cast the context to the activation something like this:

 //в классе ViewHolder ((MainActivity)itemView.getContext()).startRepeatingTask(); 

    Everything is very boring and dreary:

    1. When creating an adapter RecyclerView in the adapter's constructor we send a link to your Activity
    2. When creating a ViewHolder also ViewHolder link to the Activity from the adapter in the constructor.
    3. Bingo, now we have an Activity in the holder - in the right place we call the Activity methods

    You can certainly implement the ideologically consistent and Orthodox pattern through interfaces, but the game is hardly worth the candle.