Android 与IntentService的线程同步
我正在尝试创建一个通过intentservice发出HTTP请求的应用程序。我需要应用程序在继续操作之前等待服务完成运行(也就是说,请求返回一些数据),因为它的操作涉及到我希望从HTTP请求接收的数据的操作。我已经尝试了很多方法——信号量、CountDownLatch,但似乎对于所有这些方法,我都需要某种方法将等待/计数对象传递到intentservice,以便它可以告诉主线程该对象正在等待的位置,该对象已完成处理。我该怎么做呢?基本上,我想要一个对http服务器的同步阻塞调用,以方便地使用意图服务,因为意图服务使多线程变得容易 再次重申,只是为了确保我没有误用术语:我所说的同步和阻塞是什么意思/我想要什么:我通过向发出请求的intentservice发送意图来调用http服务器。我的UI线程,或发送此意图的线程,现在会等待请求处理完毕并返回结果后再继续运行Android 与IntentService的线程同步,android,multithreading,intentservice,thread-synchronization,Android,Multithreading,Intentservice,Thread Synchronization,我正在尝试创建一个通过intentservice发出HTTP请求的应用程序。我需要应用程序在继续操作之前等待服务完成运行(也就是说,请求返回一些数据),因为它的操作涉及到我希望从HTTP请求接收的数据的操作。我已经尝试了很多方法——信号量、CountDownLatch,但似乎对于所有这些方法,我都需要某种方法将等待/计数对象传递到intentservice,以便它可以告诉主线程该对象正在等待的位置,该对象已完成处理。我该怎么做呢?基本上,我想要一个对http服务器的同步阻塞调用,以方便地使用意图
如果您认为我在处理这个过程(以阻塞、同步的方式进行http调用)时完全错了,那么您可能选择的另一种方式是什么?谢谢 您试图做的只是IntentService和Activity/Fragment之间的通信 您可以尝试在
onHandleIntent
的末尾发送广播,并在注册的接收器中捕获广播,或使用ResultReceiver-阅读更多如何实现广播
编辑:
试试这个:
onHandleIntent
// operation 1
Bundle b1 = new Bundle();
b1.putParcelable("data", data1);
resultReceiver.send(0, b1);
// operation 2
Bundle b2 = new Bundle();
b2.putParcelable("data", data2);
resultReceiver.send(1, b2);
public void onReceiveResult(int resultCode, Bundle resultData) {
if (resultCode == 0) { // handle step 1 }
else if (resultCode == 1) { // handle step 2 }
}
public class SynchronizationManager {
private static SynchronizationManager instance;
private Object synRoot = new Object();
private boolean synchronizing = false;
private List<SynchronizationListener> synchronizationListeners;
public SynchronizationManager() {
synchronizationListeners = new ArrayList<SynchronizationListener>();
}
static {
instance = new SynchronizationManager();
}
public static SynchronizationManager getInstance() {
return instance;
}
public boolean isSynchronizing() {
synchronized (synRoot) {
return synchronizing;
}
}
public void startSynchronizing() {
synchronized (synRoot) {
if (synchronizing) {
return;
}
synchronizing = true;
}
Object data; // <-- replace Object with your data type
if (ConnectivityReceiver.hasGoodEnoughNetworkConnection()) { // check connection
data = sync();
}
synchronized (synRoot) {
synchronizing = false;
}
onSynchronizationFinish(data); // use listener for send data tu Observer Activity
}
public void stopSynchronizing() {
synchronized (synRoot) {
synchronizing = false;
}
}
public synchronized void registerSynchronizationListener(
SynchronizationListener listener) {
if (!synchronizationListeners.contains(listener)) {
synchronizationListeners.add(listener);
}
}
public synchronized void unregisterSynchronizationListener(
SynchronizationListener listener) {
if (synchronizationListeners.contains(listener)) {
synchronizationListeners.remove(listener);
}
}
public void onSynchronizationStart(int id) {
for (SynchronizationListener listener : synchronizationListeners) {
listener.onStart(id);
}
}
protected void onSynchronizationProgress(int id, long updateTime) {
for (SynchronizationListener listener : synchronizationListeners) {
listener.onProgress(id, updateTime);
}
}
protected void onSynchronizationFinish(Object data) {
for (SynchronizationListener listener : synchronizationListeners) {
listener.onFinish(data);
}
}
protected int sync) {
// code for load your data your HttpRequest
}
}
// operation 1
Bundle b1 = new Bundle();
b1.putParcelable("data", data1);
resultReceiver.send(0, b1);
// operation 2
Bundle b2 = new Bundle();
b2.putParcelable("data", data2);
resultReceiver.send(1, b2);
public void onReceiveResult(int resultCode, Bundle resultData) {
if (resultCode == 0) { // handle step 1 }
else if (resultCode == 1) { // handle step 2 }
}
public class SynchronizationManager {
private static SynchronizationManager instance;
private Object synRoot = new Object();
private boolean synchronizing = false;
private List<SynchronizationListener> synchronizationListeners;
public SynchronizationManager() {
synchronizationListeners = new ArrayList<SynchronizationListener>();
}
static {
instance = new SynchronizationManager();
}
public static SynchronizationManager getInstance() {
return instance;
}
public boolean isSynchronizing() {
synchronized (synRoot) {
return synchronizing;
}
}
public void startSynchronizing() {
synchronized (synRoot) {
if (synchronizing) {
return;
}
synchronizing = true;
}
Object data; // <-- replace Object with your data type
if (ConnectivityReceiver.hasGoodEnoughNetworkConnection()) { // check connection
data = sync();
}
synchronized (synRoot) {
synchronizing = false;
}
onSynchronizationFinish(data); // use listener for send data tu Observer Activity
}
public void stopSynchronizing() {
synchronized (synRoot) {
synchronizing = false;
}
}
public synchronized void registerSynchronizationListener(
SynchronizationListener listener) {
if (!synchronizationListeners.contains(listener)) {
synchronizationListeners.add(listener);
}
}
public synchronized void unregisterSynchronizationListener(
SynchronizationListener listener) {
if (synchronizationListeners.contains(listener)) {
synchronizationListeners.remove(listener);
}
}
public void onSynchronizationStart(int id) {
for (SynchronizationListener listener : synchronizationListeners) {
listener.onStart(id);
}
}
protected void onSynchronizationProgress(int id, long updateTime) {
for (SynchronizationListener listener : synchronizationListeners) {
listener.onProgress(id, updateTime);
}
}
protected void onSynchronizationFinish(Object data) {
for (SynchronizationListener listener : synchronizationListeners) {
listener.onFinish(data);
}
}
protected int sync) {
// code for load your data your HttpRequest
}
}
使用此模式
public interface SynchronizationListener {
//void onStart(int id); not requered
//void onProgress(int id, long updateTime); not requered
void onFinish(Object data); // replace Object with your data type
}
在您的服务中添加此结束呼叫
private void startSynchronization() {
SynchronizationManager.getInstance().startSynchronizing();
}
您的单身经理人
// operation 1
Bundle b1 = new Bundle();
b1.putParcelable("data", data1);
resultReceiver.send(0, b1);
// operation 2
Bundle b2 = new Bundle();
b2.putParcelable("data", data2);
resultReceiver.send(1, b2);
public void onReceiveResult(int resultCode, Bundle resultData) {
if (resultCode == 0) { // handle step 1 }
else if (resultCode == 1) { // handle step 2 }
}
public class SynchronizationManager {
private static SynchronizationManager instance;
private Object synRoot = new Object();
private boolean synchronizing = false;
private List<SynchronizationListener> synchronizationListeners;
public SynchronizationManager() {
synchronizationListeners = new ArrayList<SynchronizationListener>();
}
static {
instance = new SynchronizationManager();
}
public static SynchronizationManager getInstance() {
return instance;
}
public boolean isSynchronizing() {
synchronized (synRoot) {
return synchronizing;
}
}
public void startSynchronizing() {
synchronized (synRoot) {
if (synchronizing) {
return;
}
synchronizing = true;
}
Object data; // <-- replace Object with your data type
if (ConnectivityReceiver.hasGoodEnoughNetworkConnection()) { // check connection
data = sync();
}
synchronized (synRoot) {
synchronizing = false;
}
onSynchronizationFinish(data); // use listener for send data tu Observer Activity
}
public void stopSynchronizing() {
synchronized (synRoot) {
synchronizing = false;
}
}
public synchronized void registerSynchronizationListener(
SynchronizationListener listener) {
if (!synchronizationListeners.contains(listener)) {
synchronizationListeners.add(listener);
}
}
public synchronized void unregisterSynchronizationListener(
SynchronizationListener listener) {
if (synchronizationListeners.contains(listener)) {
synchronizationListeners.remove(listener);
}
}
public void onSynchronizationStart(int id) {
for (SynchronizationListener listener : synchronizationListeners) {
listener.onStart(id);
}
}
protected void onSynchronizationProgress(int id, long updateTime) {
for (SynchronizationListener listener : synchronizationListeners) {
listener.onProgress(id, updateTime);
}
}
protected void onSynchronizationFinish(Object data) {
for (SynchronizationListener listener : synchronizationListeners) {
listener.onFinish(data);
}
}
protected int sync) {
// code for load your data your HttpRequest
}
}
例如,请参见此代码在我看来,内容提供商比IntentService更好。您可以通过查询触发每个网络调用,然后返回一个MatrixCursor,其中包含有关后台工作结果的详细信息。Android在后台任务中运行查询和在触发ui更新之前等待结果方面已经有很多很好的管道 在ContentProvider query()方法中:
很抱歉,但我认为您的架构不正确,否则我可能会理解错误。IntentService是在单独的线程上以串行方式构建的。现在你说你希望它是同步的和阻塞的。你不能阻止UI线程 为了创建从IntentService到Activity/Fragment/等的通知系统,您几乎没有选择:单例、广播消息(receiver、resultReceiver)、其他 基于服务和应用程序的其他部分在同一进程中工作的假设。最好的选择是创建一个经理来完成这项工作。可以构建类似这样的功能来启动服务并侦听完成事件:
public class MyNetworkManager {
static MyNetworkManager sInstance;
Context mContext;
LinkedList<OnCompletionListener> mListeners;
private MyNetworkManager(Context context) {
mContext = context;
mListeners = new LinkedList<>();
}
public static MyNetworkManager getInstance(Context context) {
if (sInstance == null) {
synchronized (MyNetworkManager.class) {
if (sInstance == null) {
sInstance = new MyNetworkManager(context.getApplicationContext());
}
}
}
return sInstance;
}
// add listener to listen for completion event
public void addListener(OnCompletionListener listener) {
synchronized (mListeners) {
mListeners.add(listener);
}
}
// remove listener to stop listening for completion event
public void removeListener(OnCompletionListener listener) {
synchronized (mListeners) {
mListeners.remove(listener);
}
}
// call from UI to start service operation
public void startNetworkOperation() {
Intent service = new Intent();
mContext.startService(service);
}
// call from service to notify UI (still on different thread, can use Handler to make call on main thread)
public void notifyCompletion() {
synchronized (mListeners) {
for (OnCompletionListener listener : mListeners) {
listener.onCompleted(this);
}
}
}
public static interface OnCompletionListener {
void onCompleted(MyNetworkManager manager);
}
}
公共类MyNetworkManager{
静态MyNetworkManager状态;
语境;
链接列表管理员;
专用MyNetworkManager(上下文){
mContext=上下文;
mListeners=newlinkedlist();
}
公共静态MyNetworkManager getInstance(上下文){
if(sInstance==null){
已同步(MyNetworkManager.class){
if(sInstance==null){
sInstance=newmynetworkmanager(context.getApplicationContext());
}
}
}
回归承诺;
}
//添加侦听器以侦听完成事件
公共void addListener(OnCompletionListener侦听器){
已同步(mListeners){
添加(侦听器);
}
}
//删除侦听器以停止侦听完成事件
公共void RemovelListener(OnCompletionListener侦听器){
已同步(mListeners){
删除(侦听器);
}
}
//从UI调用以启动服务操作
公共无效startNetworkOperation(){
意向服务=新意向();
mContext.startService(服务);
}
//从服务调用通知UI(仍然在不同的线程上,可以使用处理程序在主线程上进行调用)
公开作废通知完成(){
已同步(mListeners){
例如(OnCompletionListener侦听器:MLListeners){
未完成(此);
}
}
}
CompletionListener上的公共静态接口{
未完成作废(MyNetworkManager);
}
}
我当前实现了一个resultreceiver,但它与片段位于同一线程上。如果不是,那么我可以实现倒计时闩锁的倒计时或信号量的释放,但是我不知道如何在我的所有类之间共享该接收器。那么为什么你甚至需要同步任何线程?您调用IntentService,等待数据,然后进行一些操作,第二次调用,等等。。。或者您有另一个异步任务或线程,您正在那里等待结果?不,这只是intentservice。第二步,调用intentservice之后。这是我的大问题。我如何等待数据?我找不到使用intent service的方法。我不知道你所说的“操作”是什么意思,所以一般的解决方案是:将所需数据保存在私有字段中,然后在从ResultReceiver获取数据后,再进行一些其他操作。此外,如果在进行这项耗时的工作时不需要更新UI,只需处理onHandleIntent
中的所有操作并返回最终结果。您能否尝试描述此模式,以便我了解其作用?这似乎真的是骗局