Android ExecutorService and ProgressBar

Viewed 496

I'm trying to implement an executorService to delete a huge Firebase node in background. This node gets a new record every ten seconds to feed a realtime linear graphic (259Krecords/month). The users need a function to clean the data from time to timen and they need to trigger it manually on demand.

I've coded the method below:

    ExecutorService executorService = Executors.newFixedThreadPool(1);
    executorService.execute(() -> {
        Log.i(TAG, "cleanTable: execute");
        tabelasRef = fbDB.child(tableName).child(dispositivoSel.getIdDispositivo());
        tabelasEventListener = new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull @NotNull DataSnapshot snapshot) {
                try{
                    Log.i(TAG, "onDataChange: childrencount " + snapshot.getChildrenCount());
                    if (snapshot.getChildrenCount() > 0) {
                        // Inicializa a ProgressBar
                        new Handler(Looper.getMainLooper()).post(() -> {
                            progressBarLimpaTabela.setMax((int) snapshot.getChildrenCount());
                            progressBarLimpaTabela.setVisibility(View.VISIBLE);
                            Log.i(TAG, "Tornando a ProgressBar visível e definindo max=" + snapshot.getChildrenCount());
                        });

                        progress = 1;
                        for (DataSnapshot ds : snapshot.getChildren()) {
                            // Apaga registro
                            fbDB.child(tableName).child(dispositivoSel.getIdDispositivo()).child(ds.getKey()).removeValue();

                            // Atualiza a ProgressBar
                            new Handler(Looper.getMainLooper()).post(() -> {
                                progressBarLimpaTabela.setProgress(progress);
                                Log.i(TAG, "Atualizando progress: " + progress);
                            });

                            progress ++;
                        }

                        // Finaliza a ProgressBar
                        new Handler(Looper.getMainLooper()).post(() -> {
                            progressBarLimpaTabela.setVisibility(View.INVISIBLE);
                            Log.i(TAG, "fechando ProgressBar.");
                        });
                    }
                }catch (Exception ex){
                    new Handler(Looper.getMainLooper()).post(() ->
                            logMsg(AdminActivity.this, tableName + "-EventListener.onDataChange(Exception): " + ex.getMessage(), true, true, false, false)
                    );
                }
            }

            @Override
            public void onCancelled(@NonNull @NotNull DatabaseError error) {
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    public void run() {
                        logMsg(AdminActivity.this, tableName + "-EventListener.onCancelled(DatabaseError): " + error.getMessage(), true, true, false, false);
                    }
                });
             }
        };
        tabelasRef.addListenerForSingleValueEvent(tabelasEventListener);
    });
    executorService.shutdown();

The thing is that the progressbar is never dispayed nor updated. I can see in logcat that it takes a while to show the logs and when it shows it comes like this:

2021-06-11 18:29:17.833 14051-14272/projectname I/LOGCAT: cleanTable: execute
2021-06-11 18:29:29.394 14051-14051/projectname I/LOGCAT: onDataChange: childrencount 105606
2021-06-11 18:30:42.405 14051-14051/projectname I/LOGCAT: Tornando a ProgressBar visível de definindo max=105606
2021-06-11 18:30:42.406 14051-14051/projectname I/LOGCAT: Atualizando progress: 105607
2021-06-11 18:30:42.526 14051-14051/projectname I/LOGCAT: Atualizando progress: 105607
2021-06-11 18:30:42.526 14051-14051/projectname I/LOGCAT: Atualizando progress: 105607
2021-06-11 18:30:42.531 14051-14051/projectname I/LOGCAT: Atualizando progress: 105607
2021-06-11 18:30:42.531 14051-14051/projectname I/LOGCAT: Atualizando progress: 105607
2021-06-11 18:30:42.607 14051-14051/projectname I/LOGCAT: Atualizando progress: 105607
2021-06-11 18:30:42.607 14051-14051/projectname I/LOGCAT: Atualizando progress: 105607
2021-06-11 18:30:42.851 14051-14051/projectname I/LOGCAT: Atualizando progress: 105607
2021-06-11 18:30:42.851 14051-14051/projectname I/LOGCAT: Atualizando progress: 105607
...
...
...
2021-06-11 18:30:48.473 14051-14051/projectname I/LOGCAT: Atualizando progress: 105607
2021-06-11 18:30:49.433 14051-14051/projectname I/LOGCAT: Atualizando progress: 105607
2021-06-11 18:30:49.433 14051-14051/projectname I/LOGCAT: fechando ProgressBar.

Please help me identify where is my mistake. Thanks!

1 Answers

I think I've found the problem. It happens that when I'm executing the "removeValue()" on firebase, it triggers it asynchronously. So, the for Loop is finished quite quickly giving me the LogCat above. I have added an OnSuccessListener to the remove command and am increasing the progress in there. Also, I've added a control variable in order to know when the processing is finished and thus close the progressbar. The end code, is like that:

    ExecutorService executorService = Executors.newSingleThreadExecutor();
    executorService.execute(() -> {
        tabelasRef = fbDB.child(tableName).child(dispositivoSel.getIdDispositivo());
        tabelasEventListener = new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull @NotNull DataSnapshot snapshot) {
                try{
                    Log.i(TAG, "onDataChange: childrencount " + snapshot.getChildrenCount());
                    if (snapshot.getChildrenCount() > 0) {
                        deleteRecCount = (int) snapshot.getChildrenCount();

                        // Inicializa a ProgressBar
                        new Handler(Looper.getMainLooper()).post(() -> {
                            progressBarLimpaTabela.setMax(deleteRecCount);
                            llayProgress.setVisibility(View.VISIBLE);
                        });

                        progress = 1;
                        for (DataSnapshot ds : snapshot.getChildren()) {
                            // Apaga registro
                            fbDB.child(tableName).child(dispositivoSel.getIdDispositivo()).child(ds.getKey()).removeValue()
                                    .addOnSuccessListener(unused -> {
                                        // Atualiza a ProgressBar
                                        new Handler(Looper.getMainLooper()).post(() -> {
                                            progressBarLimpaTabela.setProgress(progress);
                                            // Finaliza a ProgressBar
                                            if (progress == deleteRecCount){
                                                llayProgress.setVisibility(View.INVISIBLE);
                                            }
                                            progress ++;
                                        });
                                    })
                                    .addOnFailureListener(e -> Log.i(TAG, "onFailure:(" + progress + "): " + e.getMessage()))
                                    .addOnCanceledListener(() -> Log.i(TAG, "onCanceled: " + progress));
                        }

                    }
                }catch (Exception ex){
                    new Handler(Looper.getMainLooper()).post(() ->
                        logMsg(AdminActivity.this, tableName + "-EventListener.onDataChange(Exception): " + ex.getMessage(), true, true, false, false)
                    );
                }
            }

            @Override
            public void onCancelled(@NonNull @NotNull DatabaseError error) {
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    public void run() {
                        logMsg(AdminActivity.this, tableName + "-EventListener.onCancelled(DatabaseError): " + error.getMessage(), true, true, false, false);
                    }
                });
             }
        };
        tabelasRef.addListenerForSingleValueEvent(tabelasEventListener);
    });
    executorService.shutdown();
Related