Android 与IntentService的线程同步

Android 与IntentService的线程同步,android,multithreading,intentservice,thread-synchronization,Android,Multithreading,Intentservice,Thread Synchronization,我正在尝试创建一个通过intentservice发出HTTP请求的应用程序。我需要应用程序在继续操作之前等待服务完成运行(也就是说,请求返回一些数据),因为它的操作涉及到我希望从HTTP请求接收的数据的操作。我已经尝试了很多方法——信号量、CountDownLatch,但似乎对于所有这些方法,我都需要某种方法将等待/计数对象传递到intentservice,以便它可以告诉主线程该对象正在等待的位置,该对象已完成处理。我该怎么做呢?基本上,我想要一个对http服务器的同步阻塞调用,以方便地使用意图

我正在尝试创建一个通过intentservice发出HTTP请求的应用程序。我需要应用程序在继续操作之前等待服务完成运行(也就是说,请求返回一些数据),因为它的操作涉及到我希望从HTTP请求接收的数据的操作。我已经尝试了很多方法——信号量、CountDownLatch,但似乎对于所有这些方法,我都需要某种方法将等待/计数对象传递到intentservice,以便它可以告诉主线程该对象正在等待的位置,该对象已完成处理。我该怎么做呢?基本上,我想要一个对http服务器的同步阻塞调用,以方便地使用意图服务,因为意图服务使多线程变得容易

再次重申,只是为了确保我没有误用术语:我所说的同步和阻塞是什么意思/我想要什么:我通过向发出请求的intentservice发送意图来调用http服务器。我的UI线程,或发送此意图的线程,现在会等待请求处理完毕并返回结果后再继续运行


如果您认为我在处理这个过程(以阻塞、同步的方式进行http调用)时完全错了,那么您可能选择的另一种方式是什么?谢谢

您试图做的只是IntentService和Activity/Fragment之间的通信

您可以尝试在
onHandleIntent
的末尾发送广播,并在注册的接收器中捕获广播,或使用ResultReceiver-阅读更多如何实现广播

编辑:

试试这个:

  • onHandleIntent
  • 在每个步骤中,使用ResultReceiver

    // 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
        }
    }
    
  • 在ResultReceiver中处理它

    // 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
    中的所有操作并返回最终结果。您能否尝试描述此模式,以便我了解其作用?这似乎真的是骗局