片段恢复时如何从服务接收数据?

时间:2016-06-06 09:59:59

标签: java android android-fragments intentservice downloading

我的活动中有一个侧边菜单抽屉,有两个选项(“我的文件”和“同步”),每个选项都是一个片段。当我处于“同步”片段时,有一个按钮开始从服务器下载文件。这是通过在后台运行的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 + "%");
}

2 个答案:

答案 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();