Hello,

I write the program code for an abstract class, the essence of it is the processing of two buttons "<", ">" one increases something (a value in a field) the other decreases accordingly. The point is that with a short press there is a one-time change, with a long press of a button, a multiple change in something while the rate of change gradually begins to grow.

In particular, I have now created an application in which the calendar is displayed (using the datePicker) and two buttons "<", ">" that change the current month. I handle the buttons in a separate thread.

The problem is that randomly, both with a long and short press of the buttons "<", ">", my program crashes. Sometimes it also crashes when you press the "<", ">" buttons too quickly.

I suspect something has done with Threads. But specifically what is wrong can not yet find.

Please tell me what could be the problem?

Thank you very much in advance.

The code of the program of the abstract class for handling pressing the buttons "<", ">".

I would also like to explain how a long click works. After a long press on the "<", ">" button, onLongClickListener is triggered. Next, the iteration process begins, some action is repeated (the abstract class actInLongClickIncrement () ) as soon as the user lifts his finger from the button OnTouchListener fires and the iteration process ends.

Processing a short click occurs only one basic action is described in the abstract class actInShortClickIncrement () .

Here are the listeners:

/** * Function set listeners for increment button {@link #mButton_Increment}. * Listeners: OnLongListener, OnClickListener, OnTouchListener; */ public void setButtonIncrementListeners(){ // Listener for long pushing on increment button mButton_Increment.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { // Listener triggered so allow incrementing mAllowIncrement = true; /** Determine user actions in this listener */ onLongClickIncrementActions(); // Build new thread for handler long pushing on button increment. // Realize incrementing algorithm `mRepeatIncrementHandler.post(new RepeatIncrement());` runLongClickIncrementing(); return true; } }); // Listener for short pushing on increment button mButton_Increment.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // Listener triggered so allow incrementing mAllowIncrement = true; // Build new thread for handler short pushing on button increment. // Realize incrementing algorithm runShortClickIncrementing(); } }); // Listener for touch increment button // It uses for detect moment lifting up finger of user from button. // If it occur than stop incrementing in thread. mButton_Increment.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if ((event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) && mAllowIncrement) { mAllowIncrement = false; } return false; } }); } 

Here is the processing of pressing. Handling a long press on the ">" button:

 /** * Function handle long click on {@link #mButton_Increment} * * Called from function: * @see #setButtonIncrementListeners() */ public void runLongClickIncrementing(){ Log.d(TAG, "Method: runLongClickIncrementing()"); mRunLongIncrementingHandler = new Runnable() { /** For send message about updating mValue */ Message msgLongIncrement; @Override public void run() { /** if onLongClick {@link #setButtonIncrementListeners()} triggered than * {@link #mAllowIncrement = true} (allow incrementing) so begin increment */ if ( mAllowIncrement ){ /** Do some actions */ actInLongClickIncrement(); /** * For handle message */ msgLongIncrement = mViewObjectLongClickIncrementHandler.obtainMessage(); Bundle bundle = new Bundle(); /** Display in textView have to occur in intermediate handler object * {@link timeHandler}. */ bundle.putString(mDISP_VIEW_OBJECT_LONG_INCREMENT, "disp_object"); msgLongIncrement.setData(bundle); mViewObjectLongClickIncrementHandler.sendMessage(msgLongIncrement); /** Repeat */ mRepeatIncrementHandler.postDelayed(mRunLongIncrementingHandler, mDelayBetweenIterations); } } }; if (mAllowIncrement == false){ mLongIncrementThread.interrupt(); } /** There is run in separate thread. */ mLongIncrementThread = new Thread(mRunLongIncrementingHandler); mLongIncrementThread.start(); /** Handler for display object value */ mViewObjectLongClickIncrementHandler = new Handler() { @Override public void handleMessage(Message msg) { /** Check message */ Bundle bundle = msg.getData(); bundle.getString(mDISP_VIEW_OBJECT_LONG_INCREMENT); /** Set new mean in view object*/ updateViewObject(); } }; } 

Processing a short click on the ">" button:

 /** * Function handle short click on {@link #mButton_Increment} * * Called from function: * @see #setButtonIncrementListeners() */ public void runShortClickIncrementing(){ Log.d(TAG, "Function: runShortClickIncrementing()"); mRunShortIncrementingHandler = new Runnable() { /** For send message about updating mValue */ Message msgShortIncrement; @Override public void run() { /** if onLongClick {@link #setButtonIncrementListeners()} triggered than * {@link #mAllowIncrement = true} (allow incrementing) so begin increment */ if ( mAllowIncrement ){ /** Do some actions */ actInShortClickIncrement(); /** * For handle message */ msgShortIncrement = mViewObjectShortClickIncrementHandler.obtainMessage(); Bundle bundle = new Bundle(); /** Display in textView have to occur in intermediate handler object * {@link timeHandler}. */ bundle.putString(mDISP_VIEW_OBJECT_SHORT_INCREMENT, "disp_object"); msgShortIncrement.setData(bundle); mViewObjectShortClickIncrementHandler.sendMessage(msgShortIncrement); } } }; if (mAllowIncrement == false){ mShortIncrementThread.interrupt(); } /** There is run in separate thread. */ mShortIncrementThread = new Thread(mRunShortIncrementingHandler); mShortIncrementThread.start(); /** Handler for display object value */ mViewObjectShortClickIncrementHandler = new Handler() { @Override public void handleMessage(Message msg) { /** Check message */ Bundle bundle = msg.getData(); bundle.getString(mDISP_VIEW_OBJECT_SHORT_INCREMENT); /** Set new mean in view object*/ updateViewObject(); } }; } 

Implementing actInLongClickIncrement in another class to change the calendar month ( datePicker object) with a long press on the ">" button:

  @Override public void actInLongClickIncrement() { /** Forbid complete of {@link android.widget.DatePicker.OnDateChangedListener} */ isAllowReturnToSelect = false; /** Increase counter in every step */ mMonthCounter++; /** If {@link #mMonthCounter} is multiple of {@link #mMULTIPLICITY_FACTOR} * than double {@link #mMonthValue] that increase faster month */ if (mMonthCounter % mMULTIPLICITY_FACTOR == 0){ mMonthValue *= 2; } /** Get previous month */ dateOfK.add(Calendar.MONTH, mMonthValue); } 

Implementing actInShortClickIncrement in another class to change the calendar month ( datePicker object) with a short press on the ">" button ::

  @Override public void actInShortClickIncrement() { /** Forbid complete of {@link android.widget.DatePicker.OnDateChangedListener} */ isAllowReturnToSelect = false; /** Get next month */ dateOfK.add(Calendar.MONTH, 1); } 

Implementing the ** updateViewObject ** method to display the calendar month change ( datePicker object):

  @Override public void updateViewObject() { /** Update new date in {@link #mDatePicker_CalendarSetDate} object */ mDatePicker_CalendarSetDate.updateDate(dateOfK.get(Calendar.YEAR), dateOfK.get(Calendar.MONTH), dateOfK.get(Calendar.DAY_OF_MONTH) ); /** Allow complete of {@link android.widget.DatePicker.OnDateChangedListener} */ isAllowReturnToSelect = true; } 

Closed due to the fact that off-topic participants zRrr , YuriySPb ♦ , VAndrJ , Pavel Parshin , Streletz 18 May '16 at 10:06 .

It seems that this question does not correspond to the subject of the site. Those who voted to close it indicated the following reason:

  • “Questions asking for help with debugging (“ why does this code not work? ”) Should include the desired behavior, a specific problem or error, and a minimum code for playing it right in the question . Questions without an explicit description of the problem are useless for other visitors. See How to create minimal, self-sufficient and reproducible example . " - zRrr, YuriiSPb, VAndrJ, Pavel Parshin, Streletz
If the question can be reformulated according to the rules set out in the certificate , edit it .

  • four
    Understand your kilometer listings, in which you didn’t even bother to do the normal indents, nobody will be here. Show the stack trace of the error that occurred and delete tons of irrelevant code. And I glanced overlooking this canvas did not understand, why do you even need threads here? - xkor
  • one
    Why do we need to bring all this into the stream, listeners and so react without delay - pavlofff
  • @ xkor, thanks for the reply. I am very sorry, I am still a novice here, so I haven’t yet learned how to formulate my questions correctly. I have taken into account your comments, deleted all unnecessary program text, added some explanations. I left only listeners for the ">" button and handlers for a long and short click of this button. - foxis
  • @xkor, @ pavlofff, As to why I carried out the processing of clicks into a separate stream: it was written in the block of Alexander Klimov, with frequent pressing of buttons the system may hang and in this case it is better to carry out the processing of pressing into a separate stream. That's why I decided to do the processing of both long and short presses in a separate thread. - foxis
  • one
    In our case, no processing of buttons in a separate thread is required. Nothing but problems such a solution will not give you, do not complicate your life with useless problems. - pavlofff

1 answer 1

Only long-running operations should be placed into a separate thread, for example, updating the database or performing a query on the network. If you do not do anything like this in actInShortClickIncrement or actInLongClickIncrement , then you do not need threads, handlers, or messages. And do not forget that if you are using separate threads, then inside actInShortClickIncrement or actInLongClickIncrement you should not work with UI elements. And if you work there not only with local variables, but also with external fields and objects, then you need to synchronize access to them, which you judging by the falls did not do. In general, you have a problem most likely in the contents of actInShortClickIncrement and actInLongClickIncrement .

  • Many thanks for the detailed answer. - foxis
  • Added the implementation of the methods actInShortClickIncrement , actInLongClickIncrement to change the month of the displayed calendar. Also added an implementation of the updateViewObject method to display the month change in the calendar. - foxis
  • I really use the class fields (activation) in which the calendar is displayed with 2 buttons ">", "<" (for example, the variable dateOfK ). There is really no sync. I read that you cannot use graphical components inside the run () method when you start it in a separate thread, so I displayed the calendar in a separate Handler (Handler) mViewObjectLongClickIncrementHandler , which calls the ** updateViewObject () ** method to display the calendar on the screen. But about the fact that you can not use the class field was not up to date. - foxis
  • @ xkor, please tell me how to correctly transfer the field of the class in which the methods are implemented, for example, actInShortClickIncrement , actInLongClickIncrement ? Those. How to synchronize access to external fields? (You can throw links to literature or websites) Thanks in advance. - foxis
  • one
    @foxis dateOfK.add(Calendar.MONTH, 1) definitely not a long operation and there is no sense in dateOfK.add(Calendar.MONTH, 1) it into a separate stream. Creating and starting a stream will take several orders of magnitude longer. And about the synchronization of streams is written in some detail, for example, here . - xkor