forked from upstream-mirrors/OpenTracks
@@ -34,7 +34,6 @@ import androidx.loader.content.Loader;
|
||||
import de.dennisguse.opentracks.AbstractActivity;
|
||||
import de.dennisguse.opentracks.ContextualActionModeCallback;
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.adapters.ScrollVisibleViews;
|
||||
import de.dennisguse.opentracks.content.data.Marker;
|
||||
import de.dennisguse.opentracks.content.data.MarkerColumns;
|
||||
import de.dennisguse.opentracks.content.data.Track;
|
||||
@@ -43,6 +42,7 @@ import de.dennisguse.opentracks.databinding.MarkerListBinding;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||
import de.dennisguse.opentracks.ui.markers.DeleteMarkerDialogFragment.DeleteMarkerCaller;
|
||||
import de.dennisguse.opentracks.ui.util.ScrollVisibleViews;
|
||||
import de.dennisguse.opentracks.util.ActivityUtils;
|
||||
import de.dennisguse.opentracks.util.IntentUtils;
|
||||
|
||||
|
||||
@@ -23,11 +23,11 @@ import java.time.Instant;
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.adapters.ExecutorListViewService;
|
||||
import de.dennisguse.opentracks.adapters.ScrollVisibleViews;
|
||||
import de.dennisguse.opentracks.content.data.MarkerColumns;
|
||||
import de.dennisguse.opentracks.content.data.Track;
|
||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.ui.util.ExecutorListViewService;
|
||||
import de.dennisguse.opentracks.ui.util.ScrollVisibleViews;
|
||||
import de.dennisguse.opentracks.util.ListItemUtils;
|
||||
|
||||
public class MarkerResourceCursorAdapter extends ResourceCursorAdapter implements ScrollVisibleViews.VisibleViewsListener {
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package de.dennisguse.opentracks.ui.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* ExecutorService wrap that avoid the execution of the same object in a ListView.
|
||||
*
|
||||
* @param <T> the type of the object that will be used to identified the Runnable.
|
||||
*/
|
||||
public class ExecutorListViewService<T> {
|
||||
|
||||
private final List<T> enqueueObjects = new ArrayList<>();
|
||||
private final ExecutorService executorService;
|
||||
|
||||
public ExecutorListViewService(int numThreads) {
|
||||
executorService = Executors.newFixedThreadPool(numThreads);
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
enqueueObjects.clear();
|
||||
executorService.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the runnable for the object.
|
||||
*
|
||||
* @param object the Object.
|
||||
* @param runnable the Runnable.
|
||||
*/
|
||||
public void execute(T object, Runnable runnable) {
|
||||
if (!preExecute(object)) {
|
||||
return;
|
||||
}
|
||||
|
||||
new Thread(() -> {
|
||||
Future<?> future = executorService.submit(runnable);
|
||||
try {
|
||||
future.get();
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
postExecute(object);
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Before execution it must checks if the object is already enqueued.
|
||||
*
|
||||
* @param object the object to check.
|
||||
* @return true if it can be executed or false otherwise.
|
||||
*/
|
||||
private boolean preExecute(T object) {
|
||||
synchronized (enqueueObjects) {
|
||||
if (!enqueueObjects.contains(object)) {
|
||||
enqueueObjects.add(object);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* After execution remove the object from the queue.
|
||||
*
|
||||
* @param object the object to be removed from the queue.
|
||||
*/
|
||||
private void postExecute(T object) {
|
||||
synchronized (enqueueObjects) {
|
||||
enqueueObjects.remove(object);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package de.dennisguse.opentracks.ui.util;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.AbsListView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* AbsListView.OnScrollListener class that can be used to know what views in a ListView are currently visible while scrolling.
|
||||
*/
|
||||
public class ScrollVisibleViews implements AbsListView.OnScrollListener {
|
||||
private int from = -1;
|
||||
private int to = -1;
|
||||
|
||||
private final VisibleViewsListener visibleViewsListener;
|
||||
|
||||
public ScrollVisibleViews(@NonNull VisibleViewsListener visibleViewsListener) {
|
||||
this.visibleViewsListener = visibleViewsListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrollStateChanged(AbsListView view, int scrollState) {
|
||||
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE || scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING || scrollState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
|
||||
if (from >= 0 && to >= 0) {
|
||||
for (int i = from; i < to; i++) {
|
||||
View viewChild = view.getChildAt(i - from);
|
||||
visibleViewsListener.onViewVisible(viewChild, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
|
||||
from = firstVisibleItem;
|
||||
to = firstVisibleItem + visibleItemCount;
|
||||
}
|
||||
|
||||
public interface VisibleViewsListener {
|
||||
void onViewVisible(View view, int position);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user