<commit_before>package com.thebluealliance.androidclient.activities;

import android.support.v4.app.FragmentActivity;
import android.view.Menu;
import android.view.MenuItem;

import com.thebluealliance.androidclient.R;
import com.thebluealliance.androidclient.interfaces.RefreshableActivityListener;

import java.util.ArrayList;

/**
 * Created by Nathan on 4/29/2014.
 */
public abstract class RefreshableActivity extends FragmentActivity {

    private ArrayList<RefreshableActivityListener> refreshListeners = new ArrayList<>();
    private ArrayList<RefreshableActivityListener> completedRefreshListeners = new ArrayList<>();

    private Menu mOptionsMenu;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.refresh_menu, menu);
        mOptionsMenu = menu;
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.refresh:
                startRefresh();
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    public void registerRefreshableActivityListener(RefreshableActivityListener listener) {
        if (listener != null && !refreshListeners.contains(listener)) {
            refreshListeners.add(listener);
        }
    }

    public void deregisterRefreshableActivityListener(RefreshableActivityListener listener) {
        if (listener != null && refreshListeners.contains(listener)) {
            refreshListeners.remove(listener);
        }
    }

    public void refreshComplete(RefreshableActivityListener listener) {
        if (listener == null || !refreshListeners.contains(listener)) {
            return;
        }
        if (!completedRefreshListeners.contains(listener)) {
            completedRefreshListeners.add(listener);
        }
        boolean refreshComplete = true;
        if (refreshListeners.size() == completedRefreshListeners.size()) {
            for (RefreshableActivityListener rlistener : refreshListeners) {
                if (!completedRefreshListeners.contains(rlistener)) {
                    refreshComplete = false;
                }
            }
        } else {
            refreshComplete = false;
        }
        if (refreshComplete) {
            if (mOptionsMenu != null) {
                // Hide refresh indicator
                MenuItem refresh = mOptionsMenu.findItem(R.id.refresh);
                refresh.setActionView(null);
            }
            completedRefreshListeners.clear();
        }
    }

    protected void startRefresh() {
        if (refreshListeners.isEmpty()) {
            return;
        }
        for (RefreshableActivityListener listener : refreshListeners) {
            listener.onRefreshStart();
        }
        if (mOptionsMenu != null) {
            // Show refresh indicator
            MenuItem refresh = mOptionsMenu.findItem(R.id.refresh);
            refresh.setActionView(R.layout.actionbar_indeterminate_progress);
        }
    }

    protected void stopRefresh() {
        for (RefreshableActivityListener listener : refreshListeners) {
            listener.onRefreshStop();
        }
    }
}
<commit_msg>Improved refreshing framework. Now supports restarting refreshes, allows child classes to indicate if a refresh should be performed, and defines behavior for what happens when a listener is unregistered while a refresh is in progress.<commit_after>package com.thebluealliance.androidclient.activities;

import android.support.v4.app.FragmentActivity;
import android.view.Menu;
import android.view.MenuItem;

import com.thebluealliance.androidclient.R;
import com.thebluealliance.androidclient.interfaces.RefreshableActivityListener;

import java.util.ArrayList;

/**
 * Created by Nathan on 4/29/2014.
 */
public abstract class RefreshableActivity extends FragmentActivity {

    private ArrayList<RefreshableActivityListener> mRefreshListeners = new ArrayList<>();
    private ArrayList<RefreshableActivityListener> mCompletedRefreshListeners = new ArrayList<>();

    private Menu mOptionsMenu;

    private boolean mRefreshInProgress = false;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.refresh_menu, menu);
        mOptionsMenu = menu;
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.refresh:
                if (shouldRefresh()) {
                    // If a refresh is already in progress, restart it. Otherwise, begin a refresh.
                    if (!mRefreshInProgress) {
                        startRefresh();
                    } else {
                        restartRefresh();
                    }
                }
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    public synchronized void registerRefreshableActivityListener(RefreshableActivityListener listener) {
        if (listener != null && !mRefreshListeners.contains(listener)) {
            mRefreshListeners.add(listener);
        }
    }

    public synchronized void deregisterRefreshableActivityListener(RefreshableActivityListener listener) {
        if (listener != null && mRefreshListeners.contains(listener)) {
            mRefreshListeners.remove(listener);
        }
        if (listener != null && mCompletedRefreshListeners.contains(listener)) {
            mCompletedRefreshListeners.remove(listener);
        }
    }

    /*
    This can be overridden by child classes to check whether or not a refresh should take place.
    For example, this might return false if there is no network connection and a network connection
    is required to refresh data. The default return value is true.

    @return true if a refresh can and should be triggered, false if otherwise
     */
    protected boolean shouldRefresh() {
        return true;
    }

    /*
    Registered listeners call this to notify the activity that they have finished refreshing.
    Once all registered listeners have indicated that they have finished refreshing, the list
    of listeners that have reported completion is cleared and onRefreshComplete() is called.

    @param listener the listener that has finished refreshing
     */
    public synchronized void notifyRefreshComplete(RefreshableActivityListener completedListener) {
        if (completedListener == null || !mRefreshListeners.contains(completedListener)) {
            return;
        }
        if (!mCompletedRefreshListeners.contains(completedListener)) {
            mCompletedRefreshListeners.add(completedListener);
        }
        boolean refreshComplete = true;
        if (mRefreshListeners.size() == mCompletedRefreshListeners.size()) {
            for (RefreshableActivityListener listener : mRefreshListeners) {
                if (!mCompletedRefreshListeners.contains(listener)) {
                    refreshComplete = false;
                }
            }
        } else {
            refreshComplete = false;
        }
        if (refreshComplete) {
            onRefreshComplete();
            mCompletedRefreshListeners.clear();
        }
    }

    /*
    Called when all registered listeners have reported that they are done refreshing.
    This can be overridden to do custom things when refreshing is completed. However, the child class should ALWAYS
    call super.onRefreshComplete() to ensure proper behavior.
     */
    protected void onRefreshComplete() {
        if (mOptionsMenu != null) {
            // Hide refresh indicator
            MenuItem refresh = mOptionsMenu.findItem(R.id.refresh);
            refresh.setActionView(null);
        }
        mRefreshInProgress = false;
    }

    /*
    Notifies all registered listeners that they should start their refresh.
     */
    protected void startRefresh() {
        mRefreshInProgress = true;
        if (mRefreshListeners.isEmpty()) {
            return;
        }
        for (RefreshableActivityListener listener : mRefreshListeners) {
            listener.onRefreshStart();
        }
        if (mOptionsMenu != null) {
            // Show refresh indicator
            MenuItem refresh = mOptionsMenu.findItem(R.id.refresh);
            refresh.setActionView(R.layout.actionbar_indeterminate_progress);
        }
    }

    /*
    Notifies all registered listeners that they should cancel their refresh
     */
    protected void cancelRefresh() {
        for (RefreshableActivityListener listener : mRefreshListeners) {
            listener.onRefreshStop();
        }
        if (mOptionsMenu != null) {
            // Hide refresh indicator
            MenuItem refresh = mOptionsMenu.findItem(R.id.refresh);
            refresh.setActionView(null);
        }
    }

    /*
    Notifies all refresh listeners that they should stop, and immediately notifies them that they should start again.
     */
    protected void restartRefresh() {
        for (RefreshableActivityListener listener : mRefreshListeners) {
            listener.onRefreshStop();
        }
        for (RefreshableActivityListener listener : mRefreshListeners) {
            listener.onRefreshStart();
        }
        mRefreshInProgress = true;
    }
}

{'fraction_non_alphanumeric': 0.0766841597943665, 'fraction_numerical': 0.0017136125093713183, 'mean_word_length': 2.4856289660321016, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5633076', 'n_tokens_mistral': 2206, 'n_tokens_neox': 2155, 'n_words': 581}