@@ -0,0 +1,2932 @@
+package me.thekey.android.support.v4.content;%0A%0Aimport java.util.ArrayList;%0Aimport java.util.Date;%0Aimport java.util.List;%0A%0Aimport me.thekey.android.TheKey;%0Aimport me.thekey.android.TheKey.Attributes;%0Aimport me.thekey.android.TheKeySocketException;%0Aimport android.content.BroadcastReceiver;%0Aimport android.content.Context;%0Aimport android.content.Intent;%0Aimport android.content.IntentFilter;%0Aimport android.support.v4.content.AsyncTaskLoader;%0Aimport android.support.v4.content.LocalBroadcastManager;%0A%0Apublic final class AttributesLoader extends AsyncTaskLoader%3CAttributes%3E %7B%0A    private static final long DEFAULT_MAX_AGE = 24 * 60 * 60 * 1000; /* 1 day */%0A    private final long maxAge = DEFAULT_MAX_AGE;%0A%0A    private boolean refresh = false;%0A%0A    private final TheKey mTheKey;%0A    private final LocalBroadcastManager mBroadcastManager;%0A    private final BroadcastReceiver mReceiver = new BroadcastReceiver() %7B%0A        @Override%0A        public void onReceive(final Context context, final Intent intent) %7B%0A            onContentChanged();%0A        %7D%0A    %7D;%0A%0A    private final List%3CIntentFilter%3E mFilters = new ArrayList%3CIntentFilter%3E();%0A%0A    public AttributesLoader(final Context context, final TheKey thekey) %7B%0A        super(context);%0A        mTheKey = thekey;%0A        mBroadcastManager = LocalBroadcastManager.getInstance(getContext());%0A%0A        mFilters.add(new IntentFilter(TheKey.ACTION_ATTRIBUTES_LOADED));%0A        mFilters.add(new IntentFilter(TheKey.ACTION_LOGIN));%0A        mFilters.add(new IntentFilter(TheKey.ACTION_LOGOUT));%0A    %7D%0A%0A    /* BEGIN lifecycle */%0A%0A    @Override%0A    protected void onStartLoading() %7B%0A        super.onStartLoading();%0A        for (final IntentFilter filter : mFilters) %7B%0A            mBroadcastManager.registerReceiver(mReceiver, filter);%0A        %7D%0A%0A        // deliver any cached attributes%0A        final Attributes attrs = mTheKey.getAttributes();%0A        deliverResult(attrs);%0A%0A        // trigger a load if we need a refresh of the attributes%0A        if (takeContentChanged() %7C%7C needRefresh(attrs)) %7B%0A            forceLoad();%0A        %7D%0A    %7D%0A%0A    @Override%0A    protected void onAbandon() %7B%0A        mBroadcastManager.unregisterReceiver(mReceiver);%0A        super.onAbandon();%0A    %7D%0A%0A    /* END lifecycle */%0A%0A    @Override%0A    public Attributes loadInBackground() %7B%0A        Attributes attrs = mTheKey.getAttributes();%0A%0A        // check to see if the current attributes are stale%0A        if (needRefresh(attrs)) %7B%0A            try %7B%0A                mTheKey.loadAttributes();%0A                attrs = mTheKey.getAttributes();%0A            %7D catch (final TheKeySocketException ignored) %7B%0A            %7D%0A        %7D%0A%0A        // return the loaded attributes%0A        return attrs;%0A    %7D%0A%0A    private boolean needRefresh(final Attributes attrs) %7B%0A        return this.refresh %7C%7C attrs == null %7C%7C !attrs.areValid()%0A                %7C%7C attrs.getLoadedTime().before(new Date(System.currentTimeMillis() - maxAge));%0A    %7D%0A%7D%0A

create a content Loader that handles loading User Attributes in the background