2

我有一个ContentProvider从 sqlite 数据库中获取数据并通过Loader. 它由Service运行 anAsyncTask从服务器下载数据并在ContentProvider. 我希望这很清楚,但可以肯定的是:

  • ListFragmentContentProvider从via获取数据Loader

  • ContentProvider更新为Service.

现在,当我第一次启动应用程序时我的本地 sqlite 数据库为空时,它显示它没有事件,即使它们当前正在通过Service. 我宁愿ProgressBar在这一刻展示(无限旋转的轮子,而不是酒吧)。但是,如果我ProgressBar在没有来自数据库的结果时显示,即使在这种特定情况下从服务器获取数据之后,当外部数据库中没有记录时它也会存在(在我的情况下它经常发生)。所以:

  • 当我第一次下载数据时,Service 我想显示一个 ProgressBar,直到ContentProvider给出非空结果完成它的Service工作。

  • ContentProvider什么都不返回 Service完成它的工作(并获取空结果)时,我希望应用程序显示“未找到结果”。

我的问题可能是:如何通知ListFragmentService仍在运行或它完成了 ts 工作。我的意思是 - 我不应该FragmentService. 这违背了 的想法ContentProviders,不是吗?又怎样?

注意:我真的不知道哪个代码片段在这里会有所帮助,所以如果您觉得需要查看一些特定的片段,请在评论中告诉我。谢谢!

4

2 回答 2

1

有多种技术可以在Fragment/Activity和 a之间进行通信Service

其中之一是使用ResultReceiver并将其额外发送到IntentServiceIntent

您创建自定义接收器ServiceResultReceiver扩展ResultReceiver.

public class ServiceResultReceiver extends ResultReceiver {

    private Receiver mReceiver;

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

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

制作你的Fragment实现ServiceResultReceiver.Receiver接口。创建接收器并将其初始化为您的Fragment. 您比将接收器传递给服务,并且在服务中只需从意图中获取接收器并调用receiver.send()以将任何内容发送回接收器。

public class MyFragment extends ListFragment implements ServiceResultReceiver.Receiver {
    private ServiceResultReceiver mReceiver;
    ....

    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        mReceiver = new ServiceResultReceiver(new Handler());
        mReceiver.setReceiver(this);
    }

    public void startMyService() {
        final Intent intent = new Intent(getActivity(), MyService.class);
        intent.putExtra("receiver", mReceiver);
        getActivity().startService(intent);
    }

    @Override
    public void onReceiveResult(int resultCode, Bundle resultData) {
        // service finished
    }
}

public class MyService extends IntentService {
    ...
    @Override
    protected void onHandleIntent(Intent intent) {
        // download data and update database
        ....
        final ResultReceiver receiver = intent.getParcelableExtra("receiver");
        if (receiver != null) {
            receiver.send(0, null);
        }
    }
}
于 2012-07-24T21:51:25.033 回答
1

由于您对将实际进度发布回 UI 不太感兴趣,因此实现这一点的最简单方法是使用一对自定义广播,也可能使用静态布尔值来显示运行状态。

基本上,您的服务可以在开始下载和完成下载时通知您感兴趣的应用程序的任何组件。因此,您可以定义两个自定义操作字符串:

public static final String ACTION_DOWNLOADSTART = "com.mypackage.intent.ACTION_DOWNLOADSTART";
public static final String ACTION_DOWNLOADCOMPLETE = "com.mypackage.intent.ACTION_DOWNLOADCOMPLETE";

然后让您的服务在代码中的适当位置广播它们:

Intent start = new Intent(ACTION_DOWNLOADSTART);
sendBroadcast(start);

//...Service does its work

Intent finish = new Intent(ACTION_DOWNLOADCOMPLETE);
sendBroadcast(finish);

您可以在应用程序中的任何位置使用 a 注册这些回调BroadcastReceiver并采取相应措施(即检查状态ContentProvider并在必要时显示/隐藏进度)。

另一种常见的做法是,如果您希望能够检查 aService是否在任何给定点运行,只需包含一个private static boolean您可以在 a 处于活动状态时切换的成员Service(可能在onCreate()/之间,onDestroy()但可能在其他地方)和访问器方法(如isRunning(). Service然后,您的应用程序还可以通过调用该方法随时检查是否正在运行。

于 2012-07-24T22:11:44.197 回答