Android同步无效

时间:2017-05-26 22:27:28

标签: android multithreading concurrency

在我的一个Android应用中,我使用单例类来管理InApp结算。在这个课程中,我使用接口列表来通知来自InApp计费服务器的响应。

由于我的应用程序是多线程的,我希望这个列表能够同步,所以我已经完成了这个:

public class InAppPurchasesManager {
    ...
    private List<InAppPurchasesInterface> requestProductsListeners;
    ...
    public static InAppPurchasesManager getInstance() {

        if (mInstance == null) {
            mInstance = new InAppPurchasesManager();
        }
        return mInstance;
    }

    private InAppPurchasesManager() {}

    public void initInAppPurchasesManager(Application app) {
        ctxt = app.getApplicationContext();
        mInstance.requestProductsListeners = Collections.synchronizedList(new ArrayList());
    }
    ...
    public void addRequestProductListener(InAppPurchasesInterface listener)
    {
        synchronized(requestProductsListeners)
        {
            if(!requestProductsListeners.contains(listener))
                requestProductsListeners.add(listener);
        }
    }

    public void removeRequestProductListener(InAppPurchasesInterface listener)
    {
        synchronized(requestProductsListeners)
        {
            requestProductsListeners.remove(listener);
        }
    }

    private void responseOnRequestProductsAndPurchase(boolean success)
    {
        callingIabHelper = false;
        synchronized(requestProductsListeners)
        {
            for(InAppPurchasesInterface listener : requestProductsListeners)
                listener.onRequestProductsAndPurchased(success);
            return;
        }
    }
    ...
    public interface InAppPurchasesInterface {

        void onServiceStarted(boolean success);
        void onRequestProductsAndPurchased(boolean success);
        void onRequestProductPurchased(Purchase purchase, int error);

    }

}

但由于并发访问requestProductListeners,我仍然收到很多崩溃。

这是一个崩溃样本:

Fatal Exception: java.util.ConcurrentModificationException
       at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)
       at com.mypackage.managers.InAppPurchasesManager.responseOnRequestProductsAndPurchase(InAppPurchasesManager.java:173)
       at com.mypackage.managers.InAppPurchasesManager.access$100(InAppPurchasesManager.java:24)
       at com.mypackage.managers.InAppPurchasesManager$2.onQueryInventoryFinished(InAppPurchasesManager.java:145)
       at com.mypackage.auxiliary.inappbilling.IabHelper$2$1.run(IabHelper.java:741)
       at android.os.Handler.handleCallback(Handler.java:739)
       at android.os.Handler.dispatchMessage(Handler.java:95)
       at android.os.Looper.loop(Looper.java:148)
       at android.app.ActivityThread.main(ActivityThread.java:7329)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

由于我不是同步和多线程的专家,我确​​定我做错了什么。这些问题的任何解决方案是否有效? https://stackoverflow.com/a/2120409

也许添加&#34;同步&#34;到使用requestProductsListeners的方法的定义?

编辑: 我终于添加了同步但崩溃的原因是&#34; java.util.ConcurrentModificationException&#34;继续出现。

这是我现在的代码:

public class InAppPurchasesManager {
    ...
    private List<InAppPurchasesInterface> requestProductsListeners;
    ...
    public static InAppPurchasesManager getInstance() {

        if (mInstance == null) {
            mInstance = new InAppPurchasesManager();
        }
        return mInstance;
    }

    private InAppPurchasesManager() {}

    public void initInAppPurchasesManager(Application app) {
        ctxt = app.getApplicationContext();
        mInstance.requestProductsListeners = Collections.synchronizedList(new ArrayList());
    }
    ...
    public synchronized void addRequestProductListener(InAppPurchasesInterface listener)
    {
        synchronized(requestProductsListeners)
        {
            if(!requestProductsListeners.contains(listener))
                requestProductsListeners.add(listener);
        }
    }

    public synchronized void removeRequestProductListener(InAppPurchasesInterface listener)
    {
        synchronized(requestProductsListeners)
        {
            requestProductsListeners.remove(listener);
        }
    }

    private synchronized void responseOnRequestProductsAndPurchase(boolean success)
    {
        callingIabHelper = false;
        synchronized(requestProductsListeners)
        {
            for(InAppPurchasesInterface listener : requestProductsListeners)
                listener.onRequestProductsAndPurchased(success);
            return;
        }
    }
    ...
    public interface InAppPurchasesInterface {

        void onServiceStarted(boolean success);
        void onRequestProductsAndPurchased(boolean success);
        void onRequestProductPurchased(Purchase purchase, int error);

    }

}

我错过了什么?

编辑2:

要回答Maxim Blumental的评论,我添加以下信息:

  • addRequestProductListener方法(在数组中添加一个监听器)在OnResume()方法中调用一些需要产品及其价格的片段。

  • 一旦Google发送了有关产品及其价格的信息,就会调用responseOnRequestProductsAndPurchase方法(遍历调用回调的侦听器数组)。

  • 一旦刚刚提到的回调结束,就会调用removeRequestProductListener方法(从数组中删除监听器)。

  • 仅在

    中调用initInAppPurchasesManager
    public class MyApp extends MultiDexApplication {
    @Override
    public void onCreate() {
        super.onCreate();
         InAppPurchasesManager.getInstance().initInAppPurchasesManager(this);
    }
    

0 个答案:

没有答案