片段恢复后如何从服务中接收数据? [英] how to receive data from service when fragment is resumed?

查看:64
本文介绍了片段恢复后如何从服务中接收数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的活动中有一个侧面菜单抽屉,其中有2个选项(我的文件"和同步"),每个选项都是一个片段.当我处于同步"片段中时,有一个按钮可以开始从服务器下载文件.这是通过在后台运行的意图服务来完成的.我在片段中使用了一个结果接收器,该接收器不断从服务中获取下载进度(%)并将其显示在片段中.

I have a side menu drawer in my activity that has 2 options ("My files" and "Sync"), each of which is a fragment. When I am in "Sync" fragment, there is a button to start downloading files from the server. This is done through an intent service which is running in the background. I use a result receiver in my fragment which keeps getting the download progress (%) from the service and displays it in the fragment.

问题是,如果在进行下载时切换到我的文件"片段,然后又回到同步"片段,则会重置视图,并且进度会丢失.该服务一直在后台运行,但是该片段未显示进度.

The problem is that if I switch to the "My Files" fragment while the download is going on and come back to the "Sync" fragment, the view is reset and the progress is lost. The service keeps running in the background but the fragment does not show the progress.

我的问题是,当我切换该片段时,同步"片段是否仍从继续在后台运行的服务接收进度.回到同步"片段时,如何开始从服务接收进度更新.

My question is that when I switch the fragment, does the "Sync" fragment still receive the progress from the service that keeps running in the background. How do I start receiving the progress updates from the service when I go back to the "Sync" fragment.

下面是启动服务的片段中的代码.

Below is the code in the fragment that starts the service.

intent.putExtra("link", downloadLink);
syncReceiver = new SyncReceiver(new Handler());
intent.putExtra("result_receiver", syncReceiver);
getContext().startService(intent);

将下载进度发送到片段的服务中的代码.

Code in the service that sends the download progress to the fragment.

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);
}

片段中的进度接收代码.

The progress receiving code in the fragment.

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 + "%");
}

推荐答案

该片段不会得到更新,因为它可能会被破坏并重新创建.

The Fragment won't get updates since it might get destroyed and recreated.

我有一个类似的问题,我的解决方案是使用一个额外的Background-Fragment来保留ResultReceiver,而不会因设置setRetainInstance(true)而被破坏.

I had a similar problem and my solution was to have an extra background-Fragment to keep the ResultReceiver, that doesn't get destroyed by setting setRetainInstance(true).

可以在此处找到说明和可能的解决方案: https://stanmots.blogspot.com/2016/10/androids-bad-company-intentservice.html

An explanation and a possible solution can be found here: https://stanmots.blogspot.com/2016/10/androids-bad-company-intentservice.html

有关此问题的另一本好书: https://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html

Another good read concerning this problem: https://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html

所以我的解决方案是将ResultReceiver容纳在具有setRetainInstance(true)的额外Fragment内.

So my solution was to hold the ResultReceiver inside an extra Fragment having setRetainInstance(true).

为了(重新)创建视图时获得正确的状态,我在onCreate()中执行以下操作:

To get the right state when (re-)creating the View, I do the following in my 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()

In my IntentObserverFragment I start the work at onAttach() - not at onCreate(), because the needed Context isn't available yet, which would result in a NPE using e.g. 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);
}

这篇关于片段恢复后如何从服务中接收数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆