mardi 9 août 2016

Singleton pattern for an Update and Location classes in Android

My question is two-fold. First, I want to know what you guys think of the singleton pattern used for these Update and Location classes tha I'm going to describe in a second. Secondly, I'm still not sure about the naming of said classes.

Let's start with some background...

My company has this app that cannot be published on the Play store, as such, we had to develop our own update mechanism; this is for the update class. As for the location class, it's something that will connect to Google Play Services and get me a location, abstracting all the connection and updates requesting stuff. I need to request the location (I actually just need the country the user is located) just once and only then I can start my application. Until the location and update are finished, a splash screen will be shown. That's just how it is and there's nothing I can do to avoid this. But that's not relevant here.

  • UpdateManager.java - takes care of checking for a new version by downloading a .json file, comparing the versionCode, downloading a new .apk if needed with a progress bar. Has a bunch of callbacks to be used by the UpdateProvider.java below.
  • UpdateProvider.java - takes care of initializing the UpdateManager and checks for an update. Shows a dialog if a new update is available, requests permissions if the user decides to download, starts the download and eventually launches the package installer.

Now, the singleton pattern...

The gist of the UpdateProvider.java is this:

public class UpdateProvider {

    private static volatile UpdateProvider sInstance;

    private final Activity mActivity;
    private UpdateCallback mUpdateCallback;

    private UpdateProvider(Activity activity) {
        mActivity = activity;
    }

    public static UpdateProvider with(@NonNull Activity activity) {
        if (sInstance == null) {
            synchronized (UpdateProvider.class) {
                if (sInstance == null) {
                    sInstance = new UpdateProvider(activity);
                }
            }
        }

        return sInstance;
    }

    public void initialize(@NonNull UpdateCallback callback) {
        mUpdateCallback = callback;

        mUpdateManager = new UpdateManager();
        mUpdateManager.checkForNewVersion(...);
    }


    public interface UpdateCallback {
        void onUpdateCheckFinished();
    }

}

Note: Why Activity and not Context you might ask? Because this really depends on an activity to show alert dialogs and create non-UI fragments (to handle startActivityForResult/onActivityResult when launching the package manager to install the new version). With that said, I might need to clear either/both mActivity and sInstance somewhere in the code, don't you think? Where/how exactly?

And this is how it will work from MainActivity.java:

public class MainActivity extends BaseActivity implements UpdateProvider.UpdateCallback {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        UpdateProvider.with(this).initialize(this);
    }

    @Override
    public void onUpdateCheckFinished() {
        // Start doing real stuff...
    }

}

A similar implementation would be used for the location, with a different interface and callback name. Than, both these classes would work somewhat sequential, something like this:

public class MainActivity extends BaseActivity implements UpdateProvider.UpdateCallback, LocationProvider.LocationCallbak {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        LocationProvider.with(this).initialize(this);
    }

    @Override
    public void onLocationReceived(String countryCode) {
        // Do something with countryCode...

        UpdateProvider.with(this).initialize(this);
    }

    @Override
    public void onUpdateCheckFinished() {
        // Start doing real stuff...
    }

}

The second part of my question is, what do you think of LocationProvider and UpdateProvider names? I'm not really sure... I mean, LocationProvider makes a lot of sense, but UpdateProvider not so much? However, since they implement the same singleton pattern and work in a similar fashion, I'd like both names to follow some kind of pattern. Suggestions?

To finish, what do you guys think of all this?

Aucun commentaire:

Enregistrer un commentaire