package com.dropbox.sync.android.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;
import com.dropbox.sync.android.DbxAccount;
import com.dropbox.sync.android.DbxAccountManager;
import com.dropbox.sync.android.DbxException;
import com.dropbox.sync.android.DbxFileInfo;
import com.dropbox.sync.android.DbxFileSystem;
import com.dropbox.sync.android.DbxFileSystem.PathListener.Mode;
import com.dropbox.sync.android.DbxPath;
/**
* A general-use loader for loading the contents of a folder. Registers for
* changes and automatically updates when the folder contents change.
*/
public class FolderLoader extends AsyncTaskLoader<List<DbxFileInfo>> {
private final DbxPath mPath;
private final DbxAccountManager mAccountManager;
private final Comparator<DbxFileInfo> mSortComparator;
private List<DbxFileInfo> mCachedContents;
/**
* Creates a FolderLoader for the given path. Defaults to a case-insensitive i18n-aware sort.
*
* @param context
* Used to retrieve the application context
* @param path
* Path of folder to load
*/
public FolderLoader(Context context, DbxAccountManager accountManager, DbxPath path) {
this(context, accountManager, path, FolderListComparator.getNameFirst(true));
}
/**
* Creates a FolderLoader for the given path.
*
* @param context
* Used to retrieve the application context
* @param path
* Path of folder to load
* @param sortComparator
* A comparator for sorting the folder contents before they're
* delivered. May be null for no sort.
*/
public FolderLoader(Context context, DbxAccountManager accountManager, DbxPath path, Comparator<DbxFileInfo> sortComparator) {
super(context);
mAccountManager = accountManager;
mPath = path;
mSortComparator = sortComparator;
}
/** a listener that forces a reload when folder contents change */
private DbxFileSystem.PathListener mChangeListener = new DbxFileSystem.PathListener() {
@Override
public void onPathChange(DbxFileSystem fs, DbxPath registeredPath, Mode registeredMode) {
onContentChanged();
}
};
@Override
protected void onStartLoading() {
DbxFileSystem fs = getDbxFileSystem();
if (fs != null) {
fs.addPathListener(mChangeListener, mPath, Mode.PATH_OR_CHILD);
}
if (mCachedContents != null) {
deliverResult(mCachedContents);
}
if (takeContentChanged() || mCachedContents == null) {
forceLoad();
}
}
@Override
protected void onForceLoad() {
super.onForceLoad();
}
@Override
protected void onStopLoading() {
DbxFileSystem fs = getDbxFileSystem();
if (fs != null) {
fs.removePathListener(mChangeListener, mPath, Mode.PATH_OR_CHILD);
}
cancelLoad();
}
@Override
protected void onReset() {
onStopLoading();
mCachedContents = null;
}
@Override
public void deliverResult(List<DbxFileInfo> data) {
if (isReset()) {
// An async result came back after the loader is stopped
return;
}
mCachedContents = data;
if (isStarted()) {
super.deliverResult(data);
}
}
@Override
public List<DbxFileInfo> loadInBackground() {
DbxFileSystem fs = getDbxFileSystem();
if (fs != null) {
try {
List<DbxFileInfo> entries = fs.listFolder(mPath);
if (mSortComparator != null) {
Collections.sort(entries, mSortComparator);
}
return entries;
} catch (DbxException e) {
e.printStackTrace();
}
}
return new ArrayList<DbxFileInfo>(0);
}
private DbxFileSystem getDbxFileSystem() {
DbxAccount account = mAccountManager.getLinkedAccount();
if (account != null) {
try {
return DbxFileSystem.forAccount(account);
} catch (DbxException.Unauthorized e) {
// Account was unlinked asynchronously from server.
return null;
}
}
return null;
}
}