Bind to service from new Context for configuration changes or bind from app context?

前端 未结 4 1759
囚心锁ツ
囚心锁ツ 2021-02-02 02:38

I\'m trying to work out if bound service is appropriate for doing background work in my app. The requirements are that various application components can make web requests throu

4条回答
  •  被撕碎了的回忆
    2021-02-02 02:48

    So after doing some digging I think I have come up with an (as yet) untested solution.

    Firstly, based on Diane's suggestion here: https://groups.google.com/forum/#!topic/android-developers/Nb58dOQ8Xfw I should be binding to the application context - so my problem of losing the context is gone - I can maintain my ServiceConnection across configuration changed with a Non-UI fragment - great. Then when I am done I can use the app context to hand back the service connection and unbind. I shouldn't receive any leaky service connection warnings. (I should probably point out that this is a standard and recommended way to maintain instances across config changes)

    The final crux of this problem was I was unsure of whether I could bind multiple times from the same context - the documentations on bindings imply there is some dependence between the binding and the context's lifecycle and so I was worried I would have to do my own form of reference counting. I had a look at the source code and ended up here: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.2_r1/android/app/LoadedApk.java#LoadedApk.forgetServiceDispatcher%28android.content.Context%2Candroid.content.ServiceConnection%29

    Crucially, these lines:

    sd = map.get(c);
        if (sd != null) {
            map.remove(c);
            sd.doForget();
            if (map.size() == 0) {
                mServices.remove(context);
            }
    

    Reveal that the map is being used for the reference counting I was worried about.

    SO the take home is this:

    • Bound service will work fine with the app context and we SHOULD do this to prevent leaking a service connection from one activity to another during a config change
    • I can keep my service connection on a non-UI fragment safely and use it to unbind when I am done

    I'll try and post some tested code soon.

    UPDATE and tested solution: I've made some code to test this and published here: https://github.com/samskiter/BoundServiceTest

    It seems to work quite well and the non-ui fragment (data fragment) acts as a nice proxy listener during rotation changes to catch results from the service (the intention of the listeners is to closely bind the requests to the UI in order to guarantee it stays responsive. Obviously any model changes can be propagated to the UI via observers.)

    Edit: I thought I should explicitly answer the questions in the OP...

    • should I use the first method (activities with temporary contexts)? Or the second (just bind service to the app context)? The second

    • Am I right in thinking the app context can bind to the service multiple times and then unbind from it the same number of times? (I.e. that you can have multiple valid bindings PER context)? Yes

    • Could using my own context (new Context()) in the first solution cause any issues? This is not even possible

    A final summary:

    This pattern should be pretty powerful - I can prioritise network IO (or other tasks) coming from a variety of sources across my app. I could have a foreground activity making some small io the user has asked for, simultaneously I could have kicked of a foreground service to sync all my users data. Both the foregrounds service and the activity can be bound to the same Network service to get their requests done.

    All this while making sure the service lives only exactly as long as it needs to - i.e. it plays nicely with android.

    I'm excited to get this into an app soon.

    UPDATE: I've tried to write this up and give some context to the wider problem of background work in a blog entry here: http://blog.airsource.co.uk/2014/09/10/android-bound-services/

提交回复
热议问题