Search code examples
androidsingletonotto

how to manager the singleton object's live cycle (where to unregister the otto listener)?


Having a singleton dataManager object which registers the OTTO listener in its constructor to listen to data ready event. In the application the dataManager is referred anywhere as

DataManager.instance.functionOfIt()

If not call GlobalOttoBus.instance.unregister(this) for this dataManger, then it’s listener function (fun getMessage(event: DataEvent)) may get call multiple times after reopen the app.

class DataManager {

    private var mApplication: Application? = null

    companion object {
        val TAG = DataManager::class.java.name

        private var dataMgr: DataManager? = null
        val instance: DataManager?
            @Synchronized get() {
                return dataMgr
            }
    }

    constructor(application: Application) {
        mApplication = application
        dataMgr = this

        Log.e(TAG, "+++ DataManager:ctor(), GlobalOttoBus.instance.register()");

        // have no way to to unregister in this DataManager  ??? ???
        GlobalOttoBus.instance.register(this)
    }

    @Subscribe
    fun getMessage(event: DataEvent) {
        Log.e(Tag, "+++ dataMgr::getMessage(), ${this}, ${event}")
        onDataReady(event)
    }

… …
}

Where the data is ready it posts the data to otto bus:

override fun onResponse(call: Call?, response: Response?) {
            if (response!!.isSuccessful()) {

        // parse the data ……
                // then post data ready event

        var dataEvt: DataEvent = DataEvent()
                dataEvt.setPostData(posts)

                Log.d(“GsonParse”, "+++ onResponse(), call GlobalOttoBus.instance.post(dataEvt): ${dataEvt} ")

                GlobalOttoBus.instance.post(dataEvt)
}

It is observed when minimize the app (os destroys the application) and then reopen the app this DataManager’s constructor is called (a new instance in this new session) so it does the OTTO register listener again in it’s constructor.

The problem is where to unregister from the OTTO, or more of how to manage this singleton DataManager’s life cycle? After minimize the app and then reopen the app, seems the previous one is still alive/listen but not in the new app’s scope.

This is the trace

  1. first time start app, the constructor:

    08-19 11:32:33.558 5296-5296/xxxapplication E/DataManager: +++ DataManager:ctor(), GlobalOttoBus.instance.register(), this: DataManager@94fd499
    
  2. after minimize the app and the reopen the app, the constructor is called again a new instance

    08-19 11:34:14.141 5296-5296/xxxapplication E/DataManager: +++ DataManager:ctor(), GlobalOttoBus.instance.register(), DataManager@661f37d
    
  3. one post:

    08-19 11:34:15.242 5296-5380/xxxapplication W/GsonParse: +++ onResponse(), call GlobalOttoBus.instance.post(dataEvt): DataEvent@f5a0df6
    

two listeners called on different dataManager instances:

    08-19 11:34:15.242 5296-5380/xxxapplication E/DataManager: +++ dataMgr::getMessage(), DataManager@94fd499, DataEvent@f5a0df6

    08-19 11:34:15.395 5296-5380/xxxapplication E/DataManager: +++ dataMgr::getMessage(), DataManager@661f37d, DataEvent@f5a0df6

Solution

  • Find a workaround, implement the LifecycleRegistryOwner in mainActivity, so on the lifeCycle Lifecycle.Event.ON_DESTROY it means the activity is killed, so unregister the DataManger’s otto listener.

    class MainActivity : AppCompatActivity(), LifecycleRegistryOwner {
    
        private val mRegistry: LifecycleRegistry = LifecycleRegistry(this);
        private var theLifeCycleObserve: TheLifeCycleObserve? = null
    
        override fun getLifecycle() : LifecycleRegistry {
            return mRegistry
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            val toolbar = findViewById<Toolbar>(R.id.toolbar) as Toolbar
            setSupportActionBar(toolbar)
    
            ……
    
            theLifeCycleObserve = TheLifeCycleObserve(lifecycle, object : TheLifeCycleObserve.OnLifeCycleChange {
                override fun onStar() {
                }
    
                override fun onDestroy() {
                    DataManager.instance!!.unregisterOttoBus()
                    lifecycle.removeObserver(theLifeCycleObserve)
                }
    
            })
            lifecycle.addObserver(theLifeCycleObserve)
    
        }
    
    ………
    }
    
    class TheLifeCycleObserve(private var lifecycle: LifecycleRegistry?, private var lifeCycleChangeListener: OnLifeCycleChange?) : LifecycleObserver {
    
    
        interface OnLifeCycleChange {
            fun onStar()
            fun onDestroy()
        }
    
        init {}
    
        @OnLifecycleEvent(Lifecycle.Event.ON_START)
        fun onStart() {
            lifeCycleChangeListener!!.onStar()
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
        fun onDestroy() {
            lifeCycleChangeListener!!.onDestroy()
        }
    }