我目前正在运行一个 AsyncTask,它在下载文件时更新 Activity 中的进度条。问题是当我离开 Activity 并重新进入时,ProgressBar 将不再更新。
我尝试在服务中运行 AsyncTask,但我不知道如何将 ProgressBar 值发送回我的 Activity 的 UI 线程。
我目前正在运行一个 AsyncTask,它在下载文件时更新 Activity 中的进度条。问题是当我离开 Activity 并重新进入时,ProgressBar 将不再更新。
我尝试在服务中运行 AsyncTask,但我不知道如何将 ProgressBar 值发送回我的 Activity 的 UI 线程。
当您重新进入活动抓取并从静态变量或首选项设置进度。
我遇到了和你一样的问题:
我想出了类似的东西:
public class DatabaseIncompleteActivity extends RoboActivity {
private BroadcastReceiver receiver;
private ProgressDialog progressDialog;
@Inject
private DatabaseSetManager databaseSetManager;
@Inject
private DatabaseDownloadLogger databaseDownloadLogger;
private LocalBroadcastManager localBroadcastManager;
private String jobId;
private static final int ERROR_RETRY_DIALOG = 1;
private static final String ERROR_MESSAGE = "errorMsg";
@Override
protected void onCreate( Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
localBroadcastManager = LocalBroadcastManager.getInstance( this );
showProgressDialog();
if ( getLastNonConfigurationInstance() == null ) {
startService();
}
}
private void showProgressDialog() {
progressDialog = new ProgressDialog( this );
progressDialog.setMessage( getString( R.string.please_wait ) );
progressDialog.setProgressStyle( ProgressDialog.STYLE_HORIZONTAL );
progressDialog.setIndeterminate( true );
progressDialog.setCancelable( false );
progressDialog.show();
}
private void startService() {
this.jobId = UUID.randomUUID().toString();
Intent intent = new Intent( this, ClientDatabaseDroidService.class );
intent.putExtra( ClientDatabaseDroidService.JOB_ID,
jobId );
intent.putExtra( ClientDatabaseDroidService.INTERACTIVE,
true );
startService( intent );
}
private void registerListenerReceiver() {
if ( receiver != null ) {
return;
}
localBroadcastManager.registerReceiver( this.receiver = new ClientDatabaseBroadcastReceiver(),
new IntentFilter( ClientDatabaseDroidService.PROGRESS_NOTIFICATION ) );
}
@Override
protected void onPause() {
super.onPause();
unregisterListenerReceiver();
}
@Override
protected void onResume() {
super.onResume();
DatabaseDownloadLogEntry logEntry = databaseDownloadLogger.findByJobId( jobId );
// check if service finished while we were not listening
if ( logEntry != null ) {
if ( logEntry.isSuccess() )
onFinish();
else {
Bundle bundle = new Bundle();
bundle.putString( ERROR_MESSAGE,
logEntry.getErrorMessage() );
onError( bundle );
}
return;
}
registerListenerReceiver();
}
@Override
public Object onRetainNonConfigurationInstance() {
return Boolean.TRUE;
}
final class ClientDatabaseBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive( Context context, Intent intent ) {
Bundle extras = intent.getExtras();
int eventType = extras.getInt( ClientDatabaseDroidService.EVENT_TYPE );
switch ( eventType ) {
case ClientDatabaseDroidService.EVENT_TYPE_DOWNLOADING:
onDownloading( extras );
break;
case ClientDatabaseDroidService.EVENT_TYPE_FINISHED:
onFinish();
break;
case ClientDatabaseDroidService.EVENT_TYPE_ERROR:
Bundle bundle = new Bundle();
bundle.putString( ERROR_MESSAGE,
extras.getString( ClientDatabaseDroidService.EXTRA_ERROR_MESSAGE ) );
onError( bundle );
break;
default:
throw new RuntimeException( "should not happen" );
}
}
}
private void unregisterListenerReceiver() {
if ( receiver != null ) {
localBroadcastManager.unregisterReceiver( receiver );
receiver = null;
}
}
private void onError( Bundle extras ) {
progressDialog.dismiss();
showDialog( ERROR_RETRY_DIALOG,
extras );
}
private void onFinish() {
progressDialog.dismiss();
setResult( RESULT_OK );
finish();
}
@Override
protected Dialog onCreateDialog( final int id, Bundle args ) {
if ( id == ERROR_RETRY_DIALOG ) {
Builder builder = new AlertDialog.Builder( this );
builder.setTitle( R.string.error );
builder.setMessage( "" );
builder.setPositiveButton( R.string.yes,
new OnClickListener() {
@Override
public void onClick( DialogInterface dialog, int which ) {
showProgressDialog();
startService();
}
} );
builder.setNegativeButton( R.string.no,
new OnClickListener() {
@Override
public void onClick( DialogInterface dialog, int which ) {
setResult( RESULT_CANCELED );
finish();
}
} );
return builder.create();
}
return super.onCreateDialog( id,
args );
}
@Override
protected void onPrepareDialog( int id, Dialog dialog, Bundle args ) {
if ( id == ERROR_RETRY_DIALOG ) {
( (AlertDialog) dialog ).setMessage( String.format( "%s\n\n%s",
args.getString( ERROR_MESSAGE ),
getString( R.string.do_you_wish_to_retry ) ) );
return;
}
super.onPrepareDialog( id,
dialog );
}
private void onDownloading( Bundle extras ) {
String currentDatabase = extras.getString( ClientDatabaseDroidService.EXTRA_CURRENT_CLASSIFIER );
Progress databaseProgress = extras.getParcelable( ClientDatabaseDroidService.EXTRA_DATABASE_PROGRESS );
Progress downloadProgress = extras.getParcelable( ClientDatabaseDroidService.EXTRA_DOWNLOAD_PROGRESS );
progressDialog.setIndeterminate( false );
progressDialog.setMessage( String.format( "[%d/%d] %s",
databaseProgress.getProcessed(),
databaseProgress.getSize(),
currentDatabase ) );
progressDialog.setProgress( (int) downloadProgress.getProcessed() );
progressDialog.setMax( (int) downloadProgress.getSize() );
}
}
主要思想是:
希望有帮助。
这很正常。当您离开它们或旋转您的设备时,活动就会消失。然后它们被重新创建。AsyncTasks 不会自动重新链接到新的 Activity 实例。
实际上,RoboSpice是您正在寻找的库:它允许您从 Activity 启动下载、旋转设备、离开 Activity,甚至离开应用程序,甚至使用任务切换器杀死它,您的下载将继续存在。任何活动、以前活动的新实例,甚至是完全不同的活动,都可以重新链接到您的下载。
您应该从商店下载应用程序RoboSpice Motivations,它将向您解释为什么使用 AsyncTasks 进行网络不是一个好主意,并向您展示如何使用 RoboSpice。
要快速了解此问题,请查看此信息图表。
另请注意,如果您只下载二进制数据并且对 POJO 不感兴趣,那么您仍然可以使用 RoboSpice 或DownloadManager(但它的 API 不如 RoboSpice 直观)。