Android ExecutorService 和 ProgressBar
Android ExecutorService and ProgressBar
我正在尝试实现一个 executorService 以在后台删除一个巨大的 Firebase 节点。该节点每十秒获取一条新记录以提供实时线性图形(259K 条记录/月)。用户需要定时清理数据的功能,需要手动按需触发。
我编写了以下方法:
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();
问题是进度条永远不会显示或更新。我可以在 logcat 中看到显示日志需要一段时间,当它显示时它是这样的:
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.
请帮我找出我错在哪里。谢谢!
我想我已经找到问题所在了。碰巧当我在 firebase 上执行“removeValue()”时,它会异步触发。所以,for 循环很快就完成了,给了我上面的 LogCat。
我在删除命令中添加了一个 OnSuccessListener 并正在增加其中的进度。此外,我还添加了一个控制变量,以便了解处理何时完成,从而关闭进度条。结束代码,是这样的:
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();
我正在尝试实现一个 executorService 以在后台删除一个巨大的 Firebase 节点。该节点每十秒获取一条新记录以提供实时线性图形(259K 条记录/月)。用户需要定时清理数据的功能,需要手动按需触发。
我编写了以下方法:
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();
问题是进度条永远不会显示或更新。我可以在 logcat 中看到显示日志需要一段时间,当它显示时它是这样的:
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.
请帮我找出我错在哪里。谢谢!
我想我已经找到问题所在了。碰巧当我在 firebase 上执行“removeValue()”时,它会异步触发。所以,for 循环很快就完成了,给了我上面的 LogCat。 我在删除命令中添加了一个 OnSuccessListener 并正在增加其中的进度。此外,我还添加了一个控制变量,以便了解处理何时完成,从而关闭进度条。结束代码,是这样的:
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();