我的活动中有一个侧边菜单抽屉,有两个选项(“我的文件”和“同步”),每个选项都是一个片段。当我处于“同步”片段时,有一个按钮开始从服务器下载文件。这是通过在后台运行的intent服务完成的。我在我的片段中使用了一个结果接收器,它不断从服务中获取下载进度(%)并将其显示在片段中。
问题是,如果我在下载过程中切换到“我的文件”片段并返回“同步”片段,则视图会重置并且进度会丢失。该服务在后台继续运行,但片段未显示进度。
我的问题是,当我切换片段时,“同步”片段是否仍然从后台运行的服务中获得进度。当我返回“同步”片段时,如何从服务开始接收进度更新。
以下是启动服务的片段中的代码。
intent.putExtra("link", downloadLink);
syncReceiver = new SyncReceiver(new Handler());
intent.putExtra("result_receiver", syncReceiver);
getContext().startService(intent);
将下载进度发送到片段的服务中的代码。
resultReceiver = intent.getParcelableExtra("result_receiver");
link = intent.getStringExtra("link");
while ((bytesRead = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, bytesRead);
byteCount += bytesRead;
String kbs = String.valueOf(byteCount / 1024);
bundle = new Bundle();
bundle.putString("response", kbs);
bundle.putString("total_data", total_file_size);
resultReceiver.send(CONTENT_PROGRESS, bundle);
}
片段中接收代码的进度。
public class SyncReceiver extends ResultReceiver {
private static final int CONTENT_PROGRESS = 2;
public SyncReceiver(Handler handler) {
super(handler);
}
public void onReceiveResult(int resultCode, Bundle data) {
super.onReceiveResult(resultCode, data);
String response = data.getString("response");
if (resultCode == CONTENT_PROGRESS) {
updateContentProgress(response, data.getString("total_file_size");
}
}
}
private void updateContentProgress(String progress, String total_file_size) {
double current = Double.parseDouble(progress);
double totalData = 0;
totalData = Double.parseDouble(total_file_size);
String percent = String.valueOf((current / totalData) * 100);
status.setText(R.string.download_progress);
status.append(" " + percent + "%");
}
答案 0 :(得分:0)
该片段无法获取更新,因为它可能会被破坏并重新创建。
我遇到了类似的问题,我的解决方案是使用一个额外的Background-Fragment来保留ResultReceiver,而不会因设置setRetainInstance(true)
而被破坏。
可以在这里找到说明和可能的解决方案:https://stanmots.blogspot.com/2016/10/androids-bad-company-intentservice.html
关于此问题的另一本好书: https://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html
所以我的解决方案是将ResultReceiver
放在一个额外的Fragment
中,其中有setRetainInstance(true)
。
要在重新创建视图时获得正确的状态,请在onCreate()
中执行以下操作:
final FragmentManager manager = ((Activity) getContext()).getFragmentManager();
// Try to find the Fragment by tag
final IntentObserverFragment intentObserverFragment =
(IntentObserverFragment) manager.findFragmentByTag(IntentObserverFragment.TAG);
if (intentObserverFragment == null) {
// Service is not active
this.progressBar.setVisibility(View.GONE);
} else {
// Service is working - show ProgressBar or else
this.progressBar.setVisibility(View.VISIBLE);
// Stay informed and get the result when it's available
intentObserverFragment.setCallbackClass( this );
}
在我的IntentObserverFragment
中,我从onAttach()
开始工作,而不是从onCreate()
开始,因为所需的Context
尚不可用,这将导致NPE使用例如getActivity()
!
@Override
public void onAttach(Context context) {
super.onAttach(context);
final MyResultReceiver myResultReceiver = new MyResultReceiver();
final Intent intent = new Intent( context, MyIntentService.class );
intent.putExtra(MyIntentService.BUNDLE_KEY_RECEIVER, myResultReceiver);
context.startService(intent);
}
答案 1 :(得分:0)
首先将您要下载的类移到“活动”中。然后,从“您”片段调用到“类”中,以在下面检查“带有代码段的下载”状态...由于活动仍将保留对“初始下载”的引用,因此您可以跟踪进度。切换片段时,由于删除了片段,因此活动会自动终止对下载线程的引用。保持活动状态可让您跟踪多个片段。确保您的课程是公开的。
((YourBaseActivityWithProperClasses) getActivity()).trackDownloadProgress();