Minimize refresh of list of files on reception of events from FileDownloader

This commit is contained in:
David A. Velasco 2015-01-22 22:15:08 +01:00
parent 265e32dee6
commit a07937cb6f
4 changed files with 84 additions and 33 deletions

View file

@ -63,6 +63,7 @@ import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.os.Process; import android.os.Process;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.util.Pair;
public class FileDownloader extends Service implements OnDatatransferProgressListener { public class FileDownloader extends Service implements OnDatatransferProgressListener {
@ -76,6 +77,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
public static final String EXTRA_DOWNLOAD_RESULT = "RESULT"; public static final String EXTRA_DOWNLOAD_RESULT = "RESULT";
public static final String EXTRA_FILE_PATH = "FILE_PATH"; public static final String EXTRA_FILE_PATH = "FILE_PATH";
public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH"; public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH";
public static final String EXTRA_LINKED_TO_PATH = "LINKED_TO";
public static final String ACCOUNT_NAME = "ACCOUNT_NAME"; public static final String ACCOUNT_NAME = "ACCOUNT_NAME";
private static final String TAG = "FileDownloader"; private static final String TAG = "FileDownloader";
@ -97,11 +99,11 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
public static String getDownloadAddedMessage() { public static String getDownloadAddedMessage() {
return FileDownloader.class.getName().toString() + DOWNLOAD_ADDED_MESSAGE; return FileDownloader.class.getName() + DOWNLOAD_ADDED_MESSAGE;
} }
public static String getDownloadFinishMessage() { public static String getDownloadFinishMessage() {
return FileDownloader.class.getName().toString() + DOWNLOAD_FINISH_MESSAGE; return FileDownloader.class.getName() + DOWNLOAD_FINISH_MESSAGE;
} }
/** /**
@ -136,6 +138,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
final Account account = intent.getParcelableExtra(EXTRA_ACCOUNT); final Account account = intent.getParcelableExtra(EXTRA_ACCOUNT);
final OCFile file = intent.getParcelableExtra(EXTRA_FILE); final OCFile file = intent.getParcelableExtra(EXTRA_FILE);
/*
if (ACTION_CANCEL_FILE_DOWNLOAD.equals(intent.getAction())) { if (ACTION_CANCEL_FILE_DOWNLOAD.equals(intent.getAction())) {
new Thread(new Runnable() { new Thread(new Runnable() {
@ -146,11 +149,15 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
}).start(); }).start();
} else { } else {
*/
AbstractList<String> requestedDownloads = new Vector<String>(); AbstractList<String> requestedDownloads = new Vector<String>();
try { try {
DownloadFileOperation newDownload = new DownloadFileOperation(account, file); DownloadFileOperation newDownload = new DownloadFileOperation(account, file);
String downloadKey = mPendingDownloads.putIfAbsent(account, file.getRemotePath(), newDownload); Pair<String, String> putResult = mPendingDownloads.putIfAbsent(
account, file.getRemotePath(), newDownload
);
String downloadKey = putResult.first;
newDownload.addDatatransferProgressListener(this); newDownload.addDatatransferProgressListener(this);
newDownload.addDatatransferProgressListener((FileDownloaderBinder) mBinder); newDownload.addDatatransferProgressListener((FileDownloaderBinder) mBinder);
requestedDownloads.add(downloadKey); requestedDownloads.add(downloadKey);
@ -163,7 +170,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
storageManager.saveFile(file); storageManager.saveFile(file);
*/ */
sendBroadcastNewDownload(newDownload); sendBroadcastNewDownload(newDownload, putResult.second);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
Log_OC.e(TAG, "Not enough information provided in intent: " + e.getMessage()); Log_OC.e(TAG, "Not enough information provided in intent: " + e.getMessage());
@ -176,7 +183,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
msg.obj = requestedDownloads; msg.obj = requestedDownloads;
mServiceHandler.sendMessage(msg); mServiceHandler.sendMessage(msg);
} }
} //}
} }
return START_NOT_STICKY; return START_NOT_STICKY;
@ -227,14 +234,14 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
* @param file A file in the queue of pending downloads * @param file A file in the queue of pending downloads
*/ */
public void cancel(Account account, OCFile file) { public void cancel(Account account, OCFile file) {
DownloadFileOperation download = null; Pair<DownloadFileOperation, String> removeResult = mPendingDownloads.remove(account, file.getRemotePath());
download = mPendingDownloads.remove(account, file.getRemotePath()); DownloadFileOperation download = removeResult.first;
if (download != null) { if (download != null) {
download.cancel(); download.cancel();
} else { } else {
// TODO synchronize // TODO synchronize
if (mCurrentDownload.getRemotePath().startsWith(file.getRemotePath()) && if (mCurrentDownload.getRemotePath().startsWith(file.getRemotePath()) &&
account.name.equals(mLastAccount)) { account.name.equals(mLastAccount.name)) {
mCurrentDownload.cancel(); mCurrentDownload.cancel();
} }
} }
@ -381,14 +388,15 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
downloadResult = new RemoteOperationResult(e); downloadResult = new RemoteOperationResult(e);
} finally { } finally {
mPendingDownloads.remove(mLastAccount, mCurrentDownload.getRemotePath()); Pair<DownloadFileOperation, String> removeResult =
mPendingDownloads.remove(mLastAccount, mCurrentDownload.getRemotePath());
/// notify result
notifyDownloadResult(mCurrentDownload, downloadResult);
sendBroadcastDownloadFinished(mCurrentDownload, downloadResult, removeResult.second);
} }
/// notify result
notifyDownloadResult(mCurrentDownload, downloadResult);
sendBroadcastDownloadFinished(mCurrentDownload, downloadResult);
} }
} }
@ -554,15 +562,22 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
/** /**
* Sends a broadcast when a download finishes in order to the interested activities can update their view * Sends a broadcast when a download finishes in order to the interested activities can update their view
* *
* @param download Finished download operation * @param download Finished download operation
* @param downloadResult Result of the download operation * @param downloadResult Result of the download operation
* @param unlinkedFromRemotePath Path in the downloads tree where the download was unlinked from
*/ */
private void sendBroadcastDownloadFinished(DownloadFileOperation download, RemoteOperationResult downloadResult) { private void sendBroadcastDownloadFinished(
DownloadFileOperation download,
RemoteOperationResult downloadResult,
String unlinkedFromRemotePath) {
Intent end = new Intent(getDownloadFinishMessage()); Intent end = new Intent(getDownloadFinishMessage());
end.putExtra(EXTRA_DOWNLOAD_RESULT, downloadResult.isSuccess()); end.putExtra(EXTRA_DOWNLOAD_RESULT, downloadResult.isSuccess());
end.putExtra(ACCOUNT_NAME, download.getAccount().name); end.putExtra(ACCOUNT_NAME, download.getAccount().name);
end.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath()); end.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath());
end.putExtra(EXTRA_FILE_PATH, download.getSavePath()); end.putExtra(EXTRA_FILE_PATH, download.getSavePath());
if (unlinkedFromRemotePath != null) {
end.putExtra(EXTRA_LINKED_TO_PATH, unlinkedFromRemotePath);
}
sendStickyBroadcast(end); sendStickyBroadcast(end);
} }
@ -570,13 +585,15 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
/** /**
* Sends a broadcast when a new download is added to the queue. * Sends a broadcast when a new download is added to the queue.
* *
* @param download Added download operation * @param download Added download operation
* @param linkedToRemotePath Path in the downloads tree where the download was linked to
*/ */
private void sendBroadcastNewDownload(DownloadFileOperation download) { private void sendBroadcastNewDownload(DownloadFileOperation download, String linkedToRemotePath) {
Intent added = new Intent(getDownloadAddedMessage()); Intent added = new Intent(getDownloadAddedMessage());
added.putExtra(ACCOUNT_NAME, download.getAccount().name); added.putExtra(ACCOUNT_NAME, download.getAccount().name);
added.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath()); added.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath());
added.putExtra(EXTRA_FILE_PATH, download.getSavePath()); added.putExtra(EXTRA_FILE_PATH, download.getSavePath());
added.putExtra(EXTRA_LINKED_TO_PATH, linkedToRemotePath);
sendStickyBroadcast(added); sendStickyBroadcast(added);
} }
@ -584,7 +601,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
* Cancel operation * Cancel operation
* @param account ownCloud account where the remote file is stored. * @param account ownCloud account where the remote file is stored.
* @param file File OCFile * @param file File OCFile
*/ *-/
public void cancel(Account account, OCFile file){ public void cancel(Account account, OCFile file){
DownloadFileOperation download = null; DownloadFileOperation download = null;
//String targetKey = buildKey(account, file.getRemotePath()); //String targetKey = buildKey(account, file.getRemotePath());
@ -613,7 +630,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
} }
} }
*/ *-/
} else { } else {
// this is not really expected... // this is not really expected...
@ -624,5 +641,6 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
} }
} }
} }
*/
} }

View file

@ -18,6 +18,7 @@
package com.owncloud.android.files.services; package com.owncloud.android.files.services;
import android.accounts.Account; import android.accounts.Account;
import android.util.Pair;
import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.OCFile;
@ -91,7 +92,7 @@ public class IndexedForest<V> {
} }
public /* synchronized */ String putIfAbsent(Account account, String remotePath, V value) { public /* synchronized */ Pair<String, String> putIfAbsent(Account account, String remotePath, V value) {
String targetKey = buildKey(account, remotePath); String targetKey = buildKey(account, remotePath);
Node<V> valuedNode = new Node(targetKey, value); Node<V> valuedNode = new Node(targetKey, value);
mMap.putIfAbsent( mMap.putIfAbsent(
@ -121,12 +122,17 @@ public class IndexedForest<V> {
currentNode = parentNode; currentNode = parentNode;
} }
return targetKey; String linkedTo = OCFile.ROOT_PATH;
if (linked) {
linkedTo = parentNode.getKey().substring(account.name.length());
}
return new Pair<String, String>(targetKey, linkedTo);
}; };
public /* synchronized */ V remove(Account account, String remotePath) { public /* synchronized */ Pair<V, String> remove(Account account, String remotePath) {
String targetKey = buildKey(account, remotePath); String targetKey = buildKey(account, remotePath);
Node<V> firstRemoved = mMap.remove(targetKey); Node<V> firstRemoved = mMap.remove(targetKey);
String unlinkedFrom = null;
if (firstRemoved != null) { if (firstRemoved != null) {
/// remove children /// remove children
@ -135,21 +141,26 @@ public class IndexedForest<V> {
/// remove ancestors if only here due to firstRemoved /// remove ancestors if only here due to firstRemoved
Node<V> removed = firstRemoved; Node<V> removed = firstRemoved;
Node<V> parent = removed.getParent(); Node<V> parent = removed.getParent();
boolean unlinked = false;
while (parent != null) { while (parent != null) {
parent.removeChild(removed); parent.removeChild(removed);
if (!parent.hasChildren()) { if (!parent.hasChildren()) {
removed = mMap.remove(parent.getKey()); removed = mMap.remove(parent.getKey());
parent = removed.getParent(); parent = removed.getParent();
} else { } else {
parent = null; break;
} }
} }
if (parent != null) {
unlinkedFrom = parent.getKey().substring(account.name.length());
}
} }
if (firstRemoved != null) { if (firstRemoved != null) {
return firstRemoved.getPayload(); return new Pair<V, String>(firstRemoved.getPayload(), unlinkedFrom);
} else { } else {
return null; return new Pair<V, String>(null, unlinkedFrom);
} }
} }

View file

@ -1261,20 +1261,30 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener {
* current folder. * current folder.
*/ */
private class DownloadFinishReceiver extends BroadcastReceiver { private class DownloadFinishReceiver extends BroadcastReceiver {
int refreshCounter = 0;
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
try { try {
boolean sameAccount = isSameAccount(context, intent); boolean sameAccount = isSameAccount(context, intent);
String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH); String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
boolean isDescendant = isDescendant(downloadedRemotePath); boolean isDescendant = isDescendant(downloadedRemotePath);
if (sameAccount && isDescendant) { if (sameAccount && isDescendant) {
refreshListOfFilesFragment(); String linkedToRemotePath = intent.getStringExtra(FileDownloader.EXTRA_LINKED_TO_PATH);
refreshSecondFragment(intent.getAction(), downloadedRemotePath, intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false)); if (linkedToRemotePath == null || isAscendant(linkedToRemotePath)) {
Log_OC.v(TAG, "NOW: refresh #" + ++refreshCounter);
refreshListOfFilesFragment();
}
refreshSecondFragment(
intent.getAction(),
downloadedRemotePath,
intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false)
);
} }
if (mWaitingToSend != null) { if (mWaitingToSend != null) {
mWaitingToSend = getStorageManager().getFileByPath(mWaitingToSend.getRemotePath()); // Update the file to send mWaitingToSend = getStorageManager().getFileByPath(mWaitingToSend.getRemotePath());
if (mWaitingToSend.isDown()) { if (mWaitingToSend.isDown()) {
sendDownloadedFile(); sendDownloadedFile();
} }
@ -1289,7 +1299,19 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener {
private boolean isDescendant(String downloadedRemotePath) { private boolean isDescendant(String downloadedRemotePath) {
OCFile currentDir = getCurrentDir(); OCFile currentDir = getCurrentDir();
return (currentDir != null && downloadedRemotePath != null && downloadedRemotePath.startsWith(currentDir.getRemotePath())); return (
currentDir != null &&
downloadedRemotePath != null &&
downloadedRemotePath.startsWith(currentDir.getRemotePath())
);
}
private boolean isAscendant(String linkedToRemotePath) {
OCFile currentDir = getCurrentDir();
return (
currentDir != null &&
currentDir.getRemotePath().startsWith(linkedToRemotePath)
);
} }
private boolean isSameAccount(Context context, Intent intent) { private boolean isSameAccount(Context context, Intent intent) {

View file

@ -426,7 +426,7 @@ ViewPager.OnPageChangeListener, OnRemoteOperationListener {
/** /**
* Class waiting for broadcast events from the {@link FielDownloader} service. * Class waiting for broadcast events from the {@link FileDownloader} service.
* *
* Updates the UI when a download is started or finished, provided that it is relevant for the * Updates the UI when a download is started or finished, provided that it is relevant for the
* folder displayed in the gallery. * folder displayed in the gallery.