我有一个ContentProvider
从sqlite数据库中获取数据并通过Loader
加载它。它由Service
更新,运行AsyncTask
从服务器下载数据并在ContentProvider
中更新。我希望它很清楚但是要确定:
ListFragment
从ContentProvider
通过Loader
获取数据,
ContentProvider
使用Service
进行了更新。
现在,当我第一次启动应用程序时,当我的本地sqlite数据库为空时,它显示它没有任何事件,即使它们当前是通过Service
下载的。我宁愿在这一刻显示ProgressBar
(无限的旋转轮,而不是条形)。但是如果我在没有来自数据库的结果时显示ProgressBar
,那么在外部数据库中没有记录的情况下,即使在从特权情况下从服务器获取数据之后它也会存在(并且在我的情况下经常发生) )。所以:
Service
I首次下载数据时
想在ContentProvider
给出之前显示ProgressBar
非空结果或 Service
完成了它的工作。
当ContentProvider
未返回任何内容时 AND Service
完成
这是工作(并获取空结果)我希望该应用程序显示
“没有找到结果”。
我的问题可能是:如何通知ListFragment
Service
仍在运行或已完成ts作业。我的意思是 - 我不应该在Fragment
内存储对调用Service
的任何引用。这违背了ContentProviders
的想法,不是吗?怎么样?
注意:我真的不知道哪个代码片段在这里会有所帮助,所以如果您觉得需要查看某些特定的片段,请在评论中告诉我。谢谢!
答案 0 :(得分:1)
如何在Fragment
/ Activity
和Service
之间进行通信有各种技巧。
其中一位正在使用ResultReceiver并将其发送到Intent
额外的IntentService。
您可以创建自定义接收器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);
}
}
}
答案 1 :(得分: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);
您可以使用BroadcastReceiver
在应用程序的任何位置注册这些回调,并采取相应措施(例如,检查ContentProvider
的状态并在必要时显示/隐藏进度。)
另一种常见做法是,如果您希望能够检查Service
是否在任何给定点上运行,只需添加一个private static boolean
成员即可在Service
时切换}是活动的(可能在onCreate()
/ onDestroy()
之间,但可能在其他地方)和一个像isRunning()
这样的访问方法。然后,您的应用程序也可以通过调用该方法随时检查Service
是否正在运行。