org.starfishrespect.myconsumption.android.ui.BaseActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.starfishrespect.myconsumption.android.ui.BaseActivity.java

Source

package org.starfishrespect.myconsumption.android.ui;

import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.Toolbar;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
import android.widget.TextView;

import com.google.android.gms.gcm.GoogleCloudMessaging;

import org.starfishrespect.myconsumption.android.R;
import org.starfishrespect.myconsumption.android.SingleInstance;
import org.starfishrespect.myconsumption.android.events.BuildAlertEvent;
import org.starfishrespect.myconsumption.android.tasks.GCMRegister;
import org.starfishrespect.myconsumption.android.tasks.UserUpdater;
import org.starfishrespect.myconsumption.android.tasks.ConfigUpdater;
import org.starfishrespect.myconsumption.android.dao.SensorValuesDao;
import org.starfishrespect.myconsumption.android.tasks.SensorValuesUpdater;
import org.starfishrespect.myconsumption.android.tasks.StatValuesUpdater;
import org.starfishrespect.myconsumption.android.data.UserData;
import org.starfishrespect.myconsumption.android.events.ReloadConfigEvent;
import org.starfishrespect.myconsumption.android.events.ReloadStatEvent;
import org.starfishrespect.myconsumption.android.events.ReloadUserEvent;
import org.starfishrespect.myconsumption.android.ui.widget.ScrimInsetsScrollView;
import org.starfishrespect.myconsumption.android.util.MiscFunctions;
import org.starfishrespect.myconsumption.android.util.PlayServicesUtils;
import org.starfishrespect.myconsumption.android.util.PrefUtils;
import org.starfishrespect.myconsumption.android.util.UIUtils;

import java.util.ArrayList;

import de.greenrobot.event.EventBus;

import static org.starfishrespect.myconsumption.android.util.LogUtils.LOGD;
import static org.starfishrespect.myconsumption.android.util.LogUtils.LOGI;
import static org.starfishrespect.myconsumption.android.util.LogUtils.LOGW;
import static org.starfishrespect.myconsumption.android.util.LogUtils.makeLogTag;

/**
 * Every important activity of the application extends the BaseActivity. It is an abstract class
 * which purpose is to regroup the elements that are reused in every Activity. Two important widgets
 * are defined and handle in BaseActivity: the header bar and the navigation drawer. Moreover,
 * common features of the app, such as the reloading option, are also implemented there.
 *
 * S23Y (2015). Licensed under the Apache License, Version 2.0.
 * Adapted from Google I/O 2014 Android App by Thibaud Ledent
 */
public abstract class BaseActivity extends ActionBarActivity
        implements SensorValuesUpdater.UpdateFinishedCallback, UserUpdater.GetUserCallback,
        StatValuesUpdater.StatUpdateFinishedCallback, ConfigUpdater.ConfigUpdateFinishedCallback {
    private static final String TAG = makeLogTag(BaseActivity.class);

    private ObjectAnimator mStatusBarColorAnimator;
    private Handler mHandler;
    private Handler mReloadHandler;

    // Primary toolbar and drawer toggle
    private Toolbar mActionBarToolbar;

    // Navigation drawer:
    private DrawerLayout mDrawerLayout;

    // A Runnable that we should execute when the navigation drawer finishes its closing animation
    private Runnable mDeferredOnDrawerClosedRunnable;

    // variables that control the Action Bar auto hide behavior (aka "quick recall")
    private boolean mActionBarAutoHideEnabled = false;
    private boolean mActionBarShown = true;

    // views that correspond to each navdrawer item, null if not yet created
    private View[] mNavDrawerItemViews = null;

    // list of navdrawer items that were actually added to the navdrawer, in order
    private ArrayList<Integer> mNavDrawerItems = new ArrayList<Integer>();

    private ViewGroup mDrawerItemsListContainer;

    private int mNormalStatusBarColor;
    private int mThemedStatusBarColor;
    private static final TypeEvaluator ARGB_EVALUATOR = new ArgbEvaluator();

    // When set, these components will be shown/hidden in sync with the action bar
    // to implement the "quick recall" effect (the Action Bar and the header views disappear
    // when you scroll down a list, and reappear quickly when you scroll up).
    private ArrayList<View> mHideableHeaderViews = new ArrayList<View>();

    // Durations for certain animations we use:
    private static final int HEADER_HIDE_ANIM_DURATION = 300;

    // symbols for navdrawer items (indices must correspond to array below). This is
    // not a list of items that are necessarily *present* in the Nav Drawer; rather,
    // it's a list of all possible items.
    protected static final int NAVDRAWER_ITEM_CHART = 0;
    protected static final int NAVDRAWER_ITEM_STATS = 1;
    protected static final int NAVDRAWER_ITEM_COMPARISON = 2;
    protected static final int NAVDRAWER_ITEM_ADD_SENSOR = 4;
    protected static final int NAVDRAWER_ITEM_SETTINGS = 5;
    protected static final int NAVDRAWER_ITEM_INVALID = -1;
    protected static final int NAVDRAWER_ITEM_SEPARATOR = -2;
    protected static final int NAVDRAWER_ITEM_SEPARATOR_SPECIAL = -3;

    // titles for navdrawer items (indices must correspond to the above)
    private static final int[] NAVDRAWER_TITLE_RES_ID = new int[] { R.string.navdrawer_item_chart,
            R.string.navdrawer_item_stat, R.string.navdrawer_item_comparison, R.string.navdrawer_item_sign_in,
            R.string.navdrawer_item_add_sensor, R.string.navdrawer_item_settings };

    // icons for navdrawer items (indices must correspond to above array)
    private static final int[] NAVDRAWER_ICON_RES_ID = new int[] { R.drawable.ic_drawer_chart, // Chart
            R.drawable.ic_drawer_stat, // Stat
            R.drawable.ic_comparison, // Comparison
            0, // Sign in
            R.drawable.ic_add, // Add sensor
            R.drawable.ic_drawer_settings };

    // delay to launch nav drawer item, to allow close animation to play
    private static final int NAVDRAWER_LAUNCH_DELAY = 250;

    // fade in and fade out durations for the main content when switching between
    // different Activities of the app through the Nav Drawer
    private static final int MAIN_CONTENT_FADEOUT_DURATION = 150;
    private static final int MAIN_CONTENT_FADEIN_DURATION = 250;

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

        mHandler = new Handler();

        // Enable or disable each Activity depending on the form factor. This is necessary
        // because this app uses many implicit intents where we don't name the exact Activity
        // in the Intent, so there should only be one enabled Activity that handles each
        // Intent in the app.
        UIUtils.enableDisableActivitiesByFormFactor(this);

        // Initialize context, database helper, user and so on...
        SingleInstance.init(this);

        if (savedInstanceState == null) {
            registerGCMClient();
        }

        ActionBar ab = getSupportActionBar();
        if (ab != null) {
            ab.setDisplayHomeAsUpEnabled(true);
        }

        mReloadHandler = new Handler();
        mReloadHandler.postDelayed(runnable, 1000 * 60 * PrefUtils.getSyncRefresh(this));

        mThemedStatusBarColor = getResources().getColor(R.color.theme_primary_dark);
        mNormalStatusBarColor = mThemedStatusBarColor;
    }

    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            refreshData();
            mReloadHandler.postDelayed(this, 1000 * 60 * PrefUtils.getSyncRefresh(BaseActivity.this));
        }
    };

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

        View mainContent = findViewById(R.id.main_content);
        if (mainContent != null) {
            mainContent.setAlpha(0);
            mainContent.animate().alpha(1).setDuration(MAIN_CONTENT_FADEIN_DURATION);
        } else {
            LOGW(TAG, "No view with ID main_content to fade in.");
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        // Verifies the proper version of Google Play Services exists on the device.
        PlayServicesUtils.checkGooglePlaySevices(this);
    }

    /**
     * Sets up the navigation drawer as appropriate. Note that the nav drawer will be
     * different depending on whether the attendee indicated that they are attending the
     * event on-site vs. attending remotely.
     */
    private void setupNavDrawer() {
        // What nav drawer item should be selected?
        int selfItem = getSelfNavDrawerItem();

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (mDrawerLayout == null) {
            return;
        }
        mDrawerLayout.setStatusBarBackgroundColor(getResources().getColor(R.color.theme_primary_dark));
        ScrimInsetsScrollView navDrawer = (ScrimInsetsScrollView) mDrawerLayout.findViewById(R.id.navdrawer);
        if (selfItem == NAVDRAWER_ITEM_INVALID) {
            // do not show a nav drawer
            if (navDrawer != null) {
                ((ViewGroup) navDrawer.getParent()).removeView(navDrawer);
            }
            mDrawerLayout = null;
            return;
        }

        if (navDrawer != null) {
            final View chosenAccountContentView = findViewById(R.id.chosen_account_content_view);
            final View chosenAccountView = findViewById(R.id.chosen_account_view);
            final int navDrawerChosenAccountHeight = getResources()
                    .getDimensionPixelSize(R.dimen.navdrawer_chosen_account_height);
            navDrawer.setOnInsetsCallback(new ScrimInsetsScrollView.OnInsetsCallback() {
                @Override
                public void onInsetsChanged(Rect insets) {
                    ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) chosenAccountContentView
                            .getLayoutParams();
                    lp.topMargin = insets.top;
                    chosenAccountContentView.setLayoutParams(lp);

                    ViewGroup.LayoutParams lp2 = chosenAccountView.getLayoutParams();
                    lp2.height = navDrawerChosenAccountHeight + insets.top;
                    chosenAccountView.setLayoutParams(lp2);
                }
            });
        }

        if (mActionBarToolbar != null) {
            mActionBarToolbar.setNavigationIcon(R.drawable.ic_drawer);
            mActionBarToolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    mDrawerLayout.openDrawer(Gravity.START);
                }
            });
        }

        mDrawerLayout.setDrawerListener(new DrawerLayout.DrawerListener() {
            @Override
            public void onDrawerClosed(View drawerView) {
                // run deferred action, if we have one
                if (mDeferredOnDrawerClosedRunnable != null) {
                    mDeferredOnDrawerClosedRunnable.run();
                    mDeferredOnDrawerClosedRunnable = null;
                }
                onNavDrawerStateChanged(false, false);
            }

            @Override
            public void onDrawerOpened(View drawerView) {
                onNavDrawerStateChanged(true, false);
            }

            @Override
            public void onDrawerStateChanged(int newState) {
                onNavDrawerStateChanged(isNavDrawerOpen(), newState != DrawerLayout.STATE_IDLE);
            }

            @Override
            public void onDrawerSlide(View drawerView, float slideOffset) {
                onNavDrawerSlide(slideOffset);
            }
        });

        mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, Gravity.START);

        // populate the nav drawer with the correct items
        populateNavDrawer();

        // TODO could be interesting
        //        // When the user runs the app for the first time, we want to land them with the
        //        // navigation drawer open. But just the first time.
        //        if (!PrefUtils.isWelcomeDone(this)) {
        //            // first run of the app starts with the nav drawer open
        //            PrefUtils.markWelcomeDone(this);
        //            mDrawerLayout.openDrawer(Gravity.START);
        //        }
    }

    protected void autoShowOrHideActionBar(boolean show) {
        if (show == mActionBarShown) {
            return;
        }

        mActionBarShown = show;
        onActionBarAutoShowOrHide(show);
    }

    // Subclasses can override this for custom behavior
    protected void onNavDrawerStateChanged(boolean isOpen, boolean isAnimating) {
        if (mActionBarAutoHideEnabled && isOpen) {
            autoShowOrHideActionBar(true);
        }
    }

    protected void onNavDrawerSlide(float offset) {
    }

    protected boolean isNavDrawerOpen() {
        return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(Gravity.START);
    }

    /** Populates the navigation drawer with the appropriate items. */
    private void populateNavDrawer() {
        mNavDrawerItems.clear();

        // decide which items will appear in the nav drawer

        // Chart is always shown
        mNavDrawerItems.add(NAVDRAWER_ITEM_CHART);
        mNavDrawerItems.add(NAVDRAWER_ITEM_STATS);
        mNavDrawerItems.add(NAVDRAWER_ITEM_COMPARISON);

        mNavDrawerItems.add(NAVDRAWER_ITEM_SEPARATOR);
        mNavDrawerItems.add(NAVDRAWER_ITEM_ADD_SENSOR);

        mNavDrawerItems.add(NAVDRAWER_ITEM_SEPARATOR_SPECIAL);
        mNavDrawerItems.add(NAVDRAWER_ITEM_SETTINGS);

        createNavDrawerItems();
    }

    private void createNavDrawerItems() {
        mDrawerItemsListContainer = (ViewGroup) findViewById(R.id.navdrawer_items_list);
        if (mDrawerItemsListContainer == null) {
            return;
        }

        mNavDrawerItemViews = new View[mNavDrawerItems.size()];
        mDrawerItemsListContainer.removeAllViews();
        int i = 0;
        for (int itemId : mNavDrawerItems) {
            mNavDrawerItemViews[i] = makeNavDrawerItem(itemId, mDrawerItemsListContainer);
            mDrawerItemsListContainer.addView(mNavDrawerItemViews[i]);
            ++i;
        }
    }

    private View makeNavDrawerItem(final int itemId, ViewGroup container) {
        boolean selected = getSelfNavDrawerItem() == itemId;
        int layoutToInflate = 0;
        if (itemId == NAVDRAWER_ITEM_SEPARATOR) {
            layoutToInflate = R.layout.navdrawer_separator;
        } else if (itemId == NAVDRAWER_ITEM_SEPARATOR_SPECIAL) {
            layoutToInflate = R.layout.navdrawer_separator;
        } else {
            layoutToInflate = R.layout.navdrawer_item;
        }
        View view = getLayoutInflater().inflate(layoutToInflate, container, false);

        if (isSeparator(itemId)) {
            // we are done
            UIUtils.setAccessibilityIgnore(view);
            return view;
        }

        ImageView iconView = (ImageView) view.findViewById(R.id.icon);
        TextView titleView = (TextView) view.findViewById(R.id.title);
        int iconId = itemId >= 0 && itemId < NAVDRAWER_ICON_RES_ID.length ? NAVDRAWER_ICON_RES_ID[itemId] : 0;
        int titleId = itemId >= 0 && itemId < NAVDRAWER_TITLE_RES_ID.length ? NAVDRAWER_TITLE_RES_ID[itemId] : 0;

        // set icon and text
        iconView.setVisibility(iconId > 0 ? View.VISIBLE : View.GONE);
        if (iconId > 0) {
            iconView.setImageResource(iconId);
        }
        titleView.setText(getString(titleId));

        formatNavDrawerItem(view, itemId, selected);

        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onNavDrawerItemClicked(itemId);
            }
        });

        return view;
    }

    private void onNavDrawerItemClicked(final int itemId) {
        if (itemId == getSelfNavDrawerItem()) {
            mDrawerLayout.closeDrawer(Gravity.START);
            return;
        }

        if (isSpecialItem(itemId)) {
            goToNavDrawerItem(itemId);
        } else {
            // launch the target Activity after a short delay, to allow the close animation to play
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    goToNavDrawerItem(itemId);
                }
            }, NAVDRAWER_LAUNCH_DELAY);

            // change the active item on the list so the user can see the item changed
            setSelectedNavDrawerItem(itemId);
            // fade out the main content
            View mainContent = findViewById(R.id.main_content);
            if (mainContent != null) {
                mainContent.animate().alpha(0).setDuration(MAIN_CONTENT_FADEOUT_DURATION);
            }
        }

        mDrawerLayout.closeDrawer(Gravity.START);
    }

    /**
     * Sets up the given navdrawer item's appearance to the selected state. Note: this could
     * also be accomplished (perhaps more cleanly) with state-based layouts.
     */
    private void setSelectedNavDrawerItem(int itemId) {
        if (mNavDrawerItemViews != null) {
            for (int i = 0; i < mNavDrawerItemViews.length; i++) {
                if (i < mNavDrawerItems.size()) {
                    int thisItemId = mNavDrawerItems.get(i);
                    formatNavDrawerItem(mNavDrawerItemViews[i], thisItemId, itemId == thisItemId);
                }
            }
        }
    }

    private void goToNavDrawerItem(int item) {
        Intent intent;
        switch (item) {
        case NAVDRAWER_ITEM_CHART:
            intent = new Intent(this, ChartActivity.class);
            startActivity(intent);
            finish();
            break;
        case NAVDRAWER_ITEM_STATS:
            intent = new Intent(this, StatActivity.class);
            startActivity(intent);
            finish();
            break;
        case NAVDRAWER_ITEM_COMPARISON:
            intent = new Intent(this, ComparisonActivity.class);
            startActivity(intent);
            finish();
            break;
        case NAVDRAWER_ITEM_ADD_SENSOR:
            intent = new Intent(this, AddSensorActivity.class);
            startActivity(intent);
            break;
        case NAVDRAWER_ITEM_SETTINGS:
            intent = new Intent(this, SettingsActivity.class);
            startActivity(intent);
            break;
        }
    }

    private boolean isSpecialItem(int itemId) {
        return itemId == NAVDRAWER_ITEM_SETTINGS;
    }

    private void formatNavDrawerItem(View view, int itemId, boolean selected) {
        if (isSeparator(itemId)) {
            // not applicable
            return;
        }

        ImageView iconView = (ImageView) view.findViewById(R.id.icon);
        TextView titleView = (TextView) view.findViewById(R.id.title);

        if (selected) {
            view.setBackgroundResource(R.drawable.selected_navdrawer_item_background);
        }

        // configure its appearance according to whether or not it's selected
        titleView.setTextColor(selected ? getResources().getColor(R.color.navdrawer_text_color_selected)
                : getResources().getColor(R.color.navdrawer_text_color));
        iconView.setColorFilter(selected ? getResources().getColor(R.color.navdrawer_icon_tint_selected)
                : getResources().getColor(R.color.navdrawer_icon_tint));
    }

    /** Registers device on the GCM server, if necessary. */
    private void registerGCMClient() {
        // Check device for Play Services APK. If check succeeds, proceed with
        //  GCM registration.
        if (PlayServicesUtils.checkGooglePlaySevices(this)) {
            GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
            String regid = PrefUtils.getRegistrationId(this);

            if (regid.isEmpty()) {
                GCMRegister task = new GCMRegister();
                task.registerInBackground(this);
            }
        } else {
            LOGI(TAG, "No valid Google Play Services APK found.");
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    private boolean isSeparator(int itemId) {
        return itemId == NAVDRAWER_ITEM_SEPARATOR || itemId == NAVDRAWER_ITEM_SEPARATOR_SPECIAL;
    }

    protected Toolbar getActionBarToolbar() {
        if (mActionBarToolbar == null) {
            mActionBarToolbar = (Toolbar) findViewById(R.id.toolbar_actionbar);
            if (mActionBarToolbar != null) {
                setSupportActionBar(mActionBarToolbar);
            }
        }
        return mActionBarToolbar;
    }

    protected void onActionBarAutoShowOrHide(boolean shown) {
        if (mStatusBarColorAnimator != null) {
            mStatusBarColorAnimator.cancel();
        }
        mStatusBarColorAnimator = ObjectAnimator
                .ofInt(mDrawerLayout, (mDrawerLayout != null) ? "statusBarBackgroundColor" : "statusBarColor",
                        shown ? Color.BLACK : mNormalStatusBarColor, shown ? mNormalStatusBarColor : Color.BLACK)
                .setDuration(250);
        if (mDrawerLayout != null) {
            mStatusBarColorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    ViewCompat.postInvalidateOnAnimation(mDrawerLayout);
                }
            });
        }
        mStatusBarColorAnimator.setEvaluator(ARGB_EVALUATOR);
        mStatusBarColorAnimator.start();

        for (View view : mHideableHeaderViews) {
            if (shown) {
                view.animate().translationY(0).alpha(1).setDuration(HEADER_HIDE_ANIM_DURATION)
                        .setInterpolator(new DecelerateInterpolator());
            } else {
                view.animate().translationY(-view.getBottom()).alpha(0).setDuration(HEADER_HIDE_ANIM_DURATION)
                        .setInterpolator(new DecelerateInterpolator());
            }
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);

        getMenuInflater().inflate(R.menu.main, menu);

        configureStandardMenuItems(menu);

        return true;
    }

    protected void configureStandardMenuItems(Menu menu) {
        MenuItem refreshItem = menu.findItem(R.id.menu_refresh);
        if (refreshItem != null) {
            refreshItem.setVisible(true);
        }
        MenuItem disconnectItem = menu.findItem(R.id.menu_disconnect);
        if (disconnectItem != null) {
            disconnectItem.setVisible(true);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        switch (id) {
        case R.id.menu_refresh:
            refreshData();
            LOGD(TAG, "menu refresh clicked");
            return true;
        case R.id.menu_disconnect:
            SingleInstance.disconnect();
            LOGD(TAG, "menu disconnect clicked");
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * Returns the navigation drawer item that corresponds to this Activity. Subclasses
     * of BaseActivity override this to indicate what nav drawer item corresponds to them
     * Return NAVDRAWER_ITEM_INVALID to mean that this Activity should not have a Nav Drawer.
     */
    protected int getSelfNavDrawerItem() {
        return NAVDRAWER_ITEM_INVALID;
    }

    /**
     * Refresh data from server to the local Android db.
     */
    public void refreshData() {
        if (!MiscFunctions.isOnline(this)) {
            MiscFunctions.makeOfflineDialog(this).show();
            return;
        }

        showReloadLayout(true);

        // Reload the user from server to see if new sensors have been added
        UserUpdater userUpdater = new UserUpdater(SingleInstance.getUserController().getUser().getName(),
                SingleInstance.getUserController().getUser().getPassword());
        userUpdater.setGetUserCallback(this);
        userUpdater.execute();
    }

    /**
     * Show or hide a reload layout while loading data from server.
     * @param visible
     */
    private void showReloadLayout(boolean visible) {
        if (visible) {
            findViewById(R.id.layoutGlobalReloading).setVisibility(View.VISIBLE);
        } else {
            findViewById(R.id.layoutGlobalReloading).setVisibility(View.GONE);
        }
    }

    // from callback of GetUserAsyncTask
    @Override
    public void userFound(UserData user) {
        new SensorValuesDao(SingleInstance.getDatabaseHelper()).updateSensorList(user.getSensors());

        // Fetch sensor values from server
        SensorValuesUpdater updater = new SensorValuesUpdater();
        updater.setUpdateFinishedCallback(this);
        updater.refreshDB();

        // Fetch the stats from the server
        StatValuesUpdater statUpdater = new StatValuesUpdater();
        statUpdater.setUpdateFinishedCallback(this);
        statUpdater.refreshDB();

        // Fetch the config from the server
        ConfigUpdater configUpdater = new ConfigUpdater();
        configUpdater.setUpdateFinishedCallback(this);
        configUpdater.refreshDB();
    }

    // from callback of GetUserAsyncTask
    @Override
    public void userRetrieveError(Exception e) {
        new AlertDialog.Builder(this).setTitle(R.string.dialog_title_error)
                .setMessage(getString(R.string.dialog_error_update_data_error))
                .setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                }).show();
        showReloadLayout(false);
    }

    @Override
    public void onUpdateFinished() {
        SingleInstance.getUserController().loadUser();
        showReloadLayout(false);
        EventBus.getDefault().post(new ReloadUserEvent(false));
    }

    @Override
    public void onStatUpdateFinished() {
        EventBus.getDefault().post(new ReloadStatEvent(true));
    }

    @Override
    public void onConfigUpdateFinished() {
        EventBus.getDefault().post(new ReloadConfigEvent(true));
    }

    public void onEvent(BuildAlertEvent event) {
        if (!event.buildAlert())
            return;

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(R.string.dialog_title_error)
                .setMessage(this.getString(R.string.dialog_message_error_when_loading_please_reconnect))
                .setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                        SingleInstance.disconnect();
                    }
                });
        builder.show();
    }
}