Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android postDelayed Handler Inside a For Loop?

Is there any way of running a handler inside a loop? I have this code but is not working as it does not wait for the loop but executes the code right way:

final Handler handler = new Handler();


        final Runnable runnable = new Runnable() {
            public void run() {

                // need to do tasks on the UI thread
                Log.d(TAG, "runn test");

                //
                for (int i = 1; i < 6; i++) {

                    handler.postDelayed(this, 5000);

                }


            }
        };

        // trigger first time
        handler.postDelayed(runnable, 0);

Of course when I move the post delayed outside the loop works but it does not iterate nor execute the times I need:

final Handler handler = new Handler();


        final Runnable runnable = new Runnable() {
            public void run() {

                // need to do tasks on the UI thread
                Log.d(TAG, "runn test");

                //
                for (int i = 1; i < 6; i++) {
                }

                // works great! but it does not do what we need
                handler.postDelayed(this, 5000);


            }
        };

        // trigger first time
        handler.postDelayed(runnable, 0);

SOLUTION FOUND:

I need to use asyntask along with Thread.sleep(5000) in the doInBackground method:

class ExecuteAsyncTask extends AsyncTask<Object, Void, String> {


            //
            protected String doInBackground(Object... task_idx) {

                //
                String param = (String) task_idx[0];

                //
                Log.d(TAG, "xxx - iter value started task idx: " + param);

                // stop
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //
                Log.d(TAG, "xxx - iter value done " + param);
                return " done for task idx: " + param;
            }


            //
            protected void onPostExecute(String result) {
                Log.d(TAG, "xxx - task executed update ui controls: " + result);
            }

        }




        for(int i = 0; i < 6; i ++){

            //
            new ExecuteAsyncTask().execute( String.valueOf(i) );

        }
like image 378
Ivan Juarez Avatar asked Aug 18 '16 17:08

Ivan Juarez


3 Answers

Instead of using a for loop, you can let the Runnable instance call itself for a specific number of times. These calls will be posted to UI thread queue so, keep that in mind. Also, since the delay is quite large, make sure the event is still needed when you trigger it next time.

The following code should do it:

final Handler handler = new Handler(); 
int count = 0;

final Runnable runnable = new Runnable() {
    public void run() { 
        // need to do tasks on the UI thread 
        Log.d(TAG, "Run test count: " + count);
        if (count++ < 5) {
            handler.postDelayed(this, 5000);
        }
    } 
}; 

// trigger first time 
handler.post(runnable);
like image 95
Shaishav Avatar answered Nov 16 '22 12:11

Shaishav


My solution to this problem if anyone has simmilar issues:

int count = 0;
    public static void method(param1, param2, param3) {
                        Runnable r = () -> { //put method inside runnable
                        View view = listView.getChildAt(position); //action to be complete
                        if (view != null) { //if action is successfully complete
                            view.setSelected(true); //do something with this 
                        } else { //do a looper
                            if (count < 10) { //limited looper to certain number
                                count++;
                                method(param1, param2, param3); //run the method again
                        }
                };

                Handler h = new Handler(); //create a new Handler and post above thread with it
                h.postDelayed(r, 300);
             }

Basically, I have created an if-else statement where else statement runs the same method with postDelayed() again for a limited number of trials.

like image 40
Androidz Avatar answered Nov 16 '22 14:11

Androidz


This can be another solution

final Handler handler = new Handler();
Runnable runnable = new Runnable() {
    int i;
    public void run() {
        for (i = 1; i < 6; i++) {
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    // need to do tasks on the UI thread
                    Log.d(TAG, "runn test");
                }
            }, 0);
            //Add some downtime
            SystemClock.sleep(5000);
        }
    }
};
new Thread(runnable).start();
like image 2
Hasan El-Hefnawy Avatar answered Nov 16 '22 14:11

Hasan El-Hefnawy