一个fragment应该如何接收异步任务执行结果的通知?

15

我有一个使用片段(fragments)的Activity。根据用户的交互,这些片段可能会出现或消失。其中许多片段会启动一个IntentService来运行异步任务。IntentService应该如何向这些任务汇报结果?

启动任务的片段可能存在,也可能不存在。如果任务完成且启动它的片段当前处于活动状态,则应通知该片段并相应地进行操作。如果不是,则无需采取任何措施。

我考虑使用广播意图和BroadcastReceiver组件,但片段不能注册接收器,只能在活动中注册。

您会提供什么解决方案?

1个回答

10

我注意到在IOSched App(Google I/O App for Android)中存在同样的问题。

他们创建了一个DetachableResultReceiver,它继承了SDK类ResultReciever

并且他们可以很容易地在Fragments中使用它

接收器:

/**
 * Proxy {@link ResultReceiver} that offers a listener interface that can be
 * detached. Useful for when sending callbacks to a {@link Service} where a
 * listening {@link Activity} can be swapped out during configuration changes.
 */
public class DetachableResultReceiver extends ResultReceiver {
    private static final String TAG = "DetachableResultReceiver";

    private Receiver mReceiver;

    public DetachableResultReceiver(Handler handler) {
        super(handler);
    }

    public void clearReceiver() {
        mReceiver = null;
    }

    public void setReceiver(Receiver receiver) {
        mReceiver = receiver;
    }

    public interface Receiver {
        public void onReceiveResult(int resultCode, Bundle resultData);
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        if (mReceiver != null) {
            mReceiver.onReceiveResult(resultCode, resultData);
        } else {
            Log.w(TAG, "Dropping result on floor for code " + resultCode + ": "
                    + resultData.toString());
        }
    }
}

活动和片段:

public class HomeActivity extends BaseActivity {
    private static final String TAG = "HomeActivity";

    private SyncStatusUpdaterFragment mSyncStatusUpdaterFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //...

        mTagStreamFragment = (TagStreamFragment) fm.findFragmentById(R.id.fragment_tag_stream);

        mSyncStatusUpdaterFragment = (SyncStatusUpdaterFragment) fm
                .findFragmentByTag(SyncStatusUpdaterFragment.TAG);
        if (mSyncStatusUpdaterFragment == null) {
            mSyncStatusUpdaterFragment = new SyncStatusUpdaterFragment();
            fm.beginTransaction().add(mSyncStatusUpdaterFragment,
                    SyncStatusUpdaterFragment.TAG).commit();

            triggerRefresh();
        }
    }

    private void triggerRefresh() {
        final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
        intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, mSyncStatusUpdaterFragment.mReceiver);
        startService(intent);

        if (mTagStreamFragment != null) {
            mTagStreamFragment.refresh();
        }
    }

    /**
     * A non-UI fragment, retained across configuration changes, that updates its activity's UI
     * when sync status changes.
     */
    public static class SyncStatusUpdaterFragment extends Fragment
            implements DetachableResultReceiver.Receiver {
        public static final String TAG = SyncStatusUpdaterFragment.class.getName();

        private boolean mSyncing = false;
        private DetachableResultReceiver mReceiver;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setRetainInstance(true);
            mReceiver = new DetachableResultReceiver(new Handler());
            mReceiver.setReceiver(this);
        }

        /** {@inheritDoc} */
        public void onReceiveResult(int resultCode, Bundle resultData) {
            HomeActivity activity = (HomeActivity) getActivity();
            if (activity == null) {
                return;
            }

            switch (resultCode) {
                case SyncService.STATUS_RUNNING: {
                    mSyncing = true;
                    break;
                }
                //...
            }

            activity.updateRefreshStatus(mSyncing);
        }

        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            ((HomeActivity) getActivity()).updateRefreshStatus(mSyncing);
        }
    }
}

1
由于某种原因,DetachableResultReceiver的链接对我来说无法使用,如果有人需要,可以使用以下链接:http://code.google.com/p/iosched/source/search?q=+DetachableResultReceiver&origq=+DetachableResultReceiver&btnG=Search+Trunk - StackOverflowed
1
请问您能否解释一下如何使用它? - Shajeel Afzal
4
仅仅提供文档和示例的链接并不能构成一个好的回答。当这些链接失效时,这个回答将变得几乎无用。请通过提供链接文档的摘要来改进此回答。 - ahsteele
2
生活在不断前进。链接现在已经失效,我建议使用Otto来解决这个问题 - http://square.github.io/otto/ - AlexKorovyansky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接