首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ContentProvider,Loader和ProgressBar

ContentProvider,Loader和ProgressBar
EN

Stack Overflow用户
提问于 2012-07-24 20:59:49
回答 2查看 1.2K关注 0票数 2

我有一个ContentProvider,它从sqlite数据库获取数据并通过Loader加载。它由一个Service更新,它运行一个AsyncTask从服务器下载数据并在ContentProvider中更新它。我希望这是明确的,但可以肯定:

  • ListFragment通过LoaderContentProvider获取数据,
  • ContentProvider将使用Service更新。

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

  • 当数据首次被Service 下载时,我想显示一个ProgressBar,直到ContentProvider给出非空的结果 Service完成它的工作为止。
  • ContentProvider没有返回任何内容时, Service完成了它的工作(并获取了空的结果),我希望应用程序显示“没有找到结果”。

我的问题可能是:如何通知ListFragment Service仍然在运行,或者它已经完成了任务。我的意思是-我不应该在Service中存储对调用Service的任何引用。这违背了ContentProviders的想法,不是吗?那怎么做?

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-07-24 22:11:44

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

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

代码语言:javascript
复制
public static final String ACTION_DOWNLOADSTART = "com.mypackage.intent.ACTION_DOWNLOADSTART";
public static final String ACTION_DOWNLOADCOMPLETE = "com.mypackage.intent.ACTION_DOWNLOADCOMPLETE";

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

代码语言:javascript
复制
Intent start = new Intent(ACTION_DOWNLOADSTART);
sendBroadcast(start);

//...Service does its work

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

您可以在应用程序中的任何地方使用BroadcastReceiver注册这些回调,并相应地进行操作(即检查ContentProvider的状态,并在必要时显示/隐藏进度)。

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

票数 1
EN

Stack Overflow用户

发布于 2012-07-24 21:51:25

Fragment / ActivityService之间的通信技术有很多种。

其中之一是使用ResultReceiver并将其发送到IntentService中的Intent附加。

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

代码语言:javascript
复制
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()将任何东西发送回接收方。

代码语言:javascript
复制
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);
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11639213

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档