From 41647989555711c274fc59890ff4529c92304771 Mon Sep 17 00:00:00 2001 From: Catfriend1 Date: Sat, 25 Aug 2018 22:28:25 +0200 Subject: [PATCH] Stop polling when the user doesn't look at a tab (#32) * Fix status tab refresh * Stop polling when the user doesn't look at a tab --- .../fragments/DeviceListFragment.java | 93 +++++++++++++++---- .../fragments/FolderListFragment.java | 93 +++++++++++++++---- .../fragments/StatusFragment.java | 30 ++++-- 3 files changed, 170 insertions(+), 46 deletions(-) diff --git a/app/src/main/java/com/nutomic/syncthingandroid/fragments/DeviceListFragment.java b/app/src/main/java/com/nutomic/syncthingandroid/fragments/DeviceListFragment.java index 5caff4db..c96c4824 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/fragments/DeviceListFragment.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/fragments/DeviceListFragment.java @@ -2,7 +2,9 @@ package com.nutomic.syncthingandroid.fragments; import android.content.Intent; import android.os.Bundle; +import android.os.Handler; import android.support.v4.app.ListFragment; +import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -12,6 +14,7 @@ import android.widget.ListView; import com.nutomic.syncthingandroid.R; import com.nutomic.syncthingandroid.activities.DeviceActivity; +import com.nutomic.syncthingandroid.activities.MainActivity; import com.nutomic.syncthingandroid.activities.SyncthingActivity; import com.nutomic.syncthingandroid.model.Device; import com.nutomic.syncthingandroid.service.Constants; @@ -22,8 +25,6 @@ import com.nutomic.syncthingandroid.views.DevicesAdapter; import java.util.Collections; import java.util.Comparator; import java.util.List; -import java.util.Timer; -import java.util.TimerTask; /** * Displays a list of all existing devices. @@ -31,36 +32,65 @@ import java.util.TimerTask; public class DeviceListFragment extends ListFragment implements SyncthingService.OnServiceStateChangeListener, ListView.OnItemClickListener { + private final static String TAG = "DeviceListFragment"; + private final static Comparator DEVICES_COMPARATOR = (lhs, rhs) -> lhs.name.compareTo(rhs.name); - private DevicesAdapter mAdapter; + private Runnable mUpdateListRunnable = new Runnable() { + @Override + public void run() { + onTimerEvent(); + mUpdateListHandler.postDelayed(this, Constants.GUI_UPDATE_INTERVAL); + } + }; - private Timer mTimer; + private final Handler mUpdateListHandler = new Handler(); + private Boolean mLastVisibleToUser = false; + private DevicesAdapter mAdapter; + private SyncthingService.State mServiceState = SyncthingService.State.INIT; + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) + { + super.setUserVisibleHint(isVisibleToUser); + if (isVisibleToUser) { + // User switched to the current tab, start handler. + startUpdateListHandler(); + } else { + // User switched away to another tab, stop handler. + stopUpdateListHandler(); + } + mLastVisibleToUser = isVisibleToUser; + } @Override public void onPause() { + stopUpdateListHandler(); super.onPause(); - if (mTimer != null) { - mTimer.cancel(); + } + + @Override + public void onResume() { + super.onResume(); + if (mLastVisibleToUser) { + startUpdateListHandler(); } } + private void startUpdateListHandler() { + Log.v(TAG, "startUpdateListHandler"); + mUpdateListHandler.removeCallbacks(mUpdateListRunnable); + mUpdateListHandler.post(mUpdateListRunnable); + } + + private void stopUpdateListHandler() { + Log.v(TAG, "stopUpdateListHandler"); + mUpdateListHandler.removeCallbacks(mUpdateListRunnable); + } + @Override public void onServiceStateChange(SyncthingService.State currentState) { - if (currentState != SyncthingService.State.ACTIVE) - return; - - mTimer = new Timer(); - mTimer.schedule(new TimerTask() { - @Override - public void run() { - if (getActivity() == null) - return; - - getActivity().runOnUiThread(DeviceListFragment.this::updateList); - } - - }, 0, Constants.GUI_UPDATE_INTERVAL); + mServiceState = currentState; } @Override @@ -72,6 +102,29 @@ public class DeviceListFragment extends ListFragment implements SyncthingService getListView().setOnItemClickListener(this); } + /** + * Invokes updateList which polls the REST API for device status updates + * while the user is looking at the current tab. + */ + private void onTimerEvent() { + if (mServiceState != SyncthingService.State.ACTIVE) { + return; + } + MainActivity mainActivity = (MainActivity) getActivity(); + if (mainActivity == null) { + return; + } + if (mainActivity.isFinishing()) { + return; + } + RestApi restApi = mainActivity.getApi(); + if (restApi == null) { + return; + } + Log.v(TAG, "Invoking updateList on UI thread"); + mainActivity.runOnUiThread(DeviceListFragment.this::updateList); + } + /** * Refreshes ListView by updating devices and info. * diff --git a/app/src/main/java/com/nutomic/syncthingandroid/fragments/FolderListFragment.java b/app/src/main/java/com/nutomic/syncthingandroid/fragments/FolderListFragment.java index ca84ed1f..d7382f10 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/fragments/FolderListFragment.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/fragments/FolderListFragment.java @@ -2,7 +2,9 @@ package com.nutomic.syncthingandroid.fragments; import android.content.Intent; import android.os.Bundle; +import android.os.Handler; import android.support.v4.app.ListFragment; +import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -11,6 +13,7 @@ import android.widget.AdapterView; import com.nutomic.syncthingandroid.R; import com.nutomic.syncthingandroid.activities.FolderActivity; +import com.nutomic.syncthingandroid.activities.MainActivity; import com.nutomic.syncthingandroid.activities.SyncthingActivity; import com.nutomic.syncthingandroid.model.Folder; import com.nutomic.syncthingandroid.service.Constants; @@ -19,8 +22,6 @@ import com.nutomic.syncthingandroid.service.SyncthingService; import com.nutomic.syncthingandroid.views.FoldersAdapter; import java.util.List; -import java.util.Timer; -import java.util.TimerTask; /** * Displays a list of all existing folders. @@ -28,34 +29,63 @@ import java.util.TimerTask; public class FolderListFragment extends ListFragment implements SyncthingService.OnServiceStateChangeListener, AdapterView.OnItemClickListener { - private FoldersAdapter mAdapter; + private final static String TAG = "FolderListFragment"; - private Timer mTimer; + private Runnable mUpdateListRunnable = new Runnable() { + @Override + public void run() { + onTimerEvent(); + mUpdateListHandler.postDelayed(this, Constants.GUI_UPDATE_INTERVAL); + } + }; + + private final Handler mUpdateListHandler = new Handler(); + private Boolean mLastVisibleToUser = false; + private FoldersAdapter mAdapter; + private SyncthingService.State mServiceState = SyncthingService.State.INIT; + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) + { + super.setUserVisibleHint(isVisibleToUser); + if (isVisibleToUser) { + // User switched to the current tab, start handler. + startUpdateListHandler(); + } else { + // User switched away to another tab, stop handler. + stopUpdateListHandler(); + } + mLastVisibleToUser = isVisibleToUser; + } @Override public void onPause() { + stopUpdateListHandler(); super.onPause(); - if (mTimer != null) { - mTimer.cancel(); + } + + @Override + public void onResume() { + super.onResume(); + if (mLastVisibleToUser) { + startUpdateListHandler(); } } + private void startUpdateListHandler() { + Log.v(TAG, "startUpdateListHandler"); + mUpdateListHandler.removeCallbacks(mUpdateListRunnable); + mUpdateListHandler.post(mUpdateListRunnable); + } + + private void stopUpdateListHandler() { + Log.v(TAG, "stopUpdateListHandler"); + mUpdateListHandler.removeCallbacks(mUpdateListRunnable); + } + @Override public void onServiceStateChange(SyncthingService.State currentState) { - if (currentState != SyncthingService.State.ACTIVE) - return; - - mTimer = new Timer(); - mTimer.schedule(new TimerTask() { - @Override - public void run() { - if (getActivity() == null) - return; - - getActivity().runOnUiThread(FolderListFragment.this::updateList); - } - - }, 0, Constants.GUI_UPDATE_INTERVAL); + mServiceState = currentState; } @Override @@ -67,6 +97,29 @@ public class FolderListFragment extends ListFragment implements SyncthingService getListView().setOnItemClickListener(this); } + /** + * Invokes updateList which polls the REST API for folder status updates + * while the user is looking at the current tab. + */ + private void onTimerEvent() { + if (mServiceState != SyncthingService.State.ACTIVE) { + return; + } + MainActivity mainActivity = (MainActivity) getActivity(); + if (mainActivity == null) { + return; + } + if (mainActivity.isFinishing()) { + return; + } + RestApi restApi = mainActivity.getApi(); + if (restApi == null) { + return; + } + Log.v(TAG, "Invoking updateList on UI thread"); + mainActivity.runOnUiThread(FolderListFragment.this::updateList); + } + /** * Refreshes ListView by updating folders and info. * diff --git a/app/src/main/java/com/nutomic/syncthingandroid/fragments/StatusFragment.java b/app/src/main/java/com/nutomic/syncthingandroid/fragments/StatusFragment.java index 40727b05..6fa52383 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/fragments/StatusFragment.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/fragments/StatusFragment.java @@ -74,23 +74,41 @@ public class StatusFragment extends ListFragment implements SyncthingService.OnS public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); - if (isVisibleToUser && !mLastVisibleToUser) { + if (isVisibleToUser) { // User switched to the current tab, start handler. - mRestApiQueryHandler.post(mRestApiQueryRunnable); - - } else if (!isVisibleToUser && mLastVisibleToUser) { + startRestApiQueryHandler(); + } else { // User switched away to another tab, stop handler. - mRestApiQueryHandler.removeCallbacks(mRestApiQueryRunnable); + stopRestApiQueryHandler(); } mLastVisibleToUser = isVisibleToUser; } @Override public void onPause() { - mRestApiQueryHandler.removeCallbacks(mRestApiQueryRunnable); + stopRestApiQueryHandler(); super.onPause(); } + @Override + public void onResume() { + super.onResume(); + if (mLastVisibleToUser) { + startRestApiQueryHandler(); + } + } + + private void startRestApiQueryHandler() { + Log.v(TAG, "startUpdateListHandler"); + mRestApiQueryHandler.removeCallbacks(mRestApiQueryRunnable); + mRestApiQueryHandler.post(mRestApiQueryRunnable); + } + + private void stopRestApiQueryHandler() { + Log.v(TAG, "stopUpdateListHandler"); + mRestApiQueryHandler.removeCallbacks(mRestApiQueryRunnable); + } + @Override public void onServiceStateChange(SyncthingService.State currentState) { mServiceState = currentState;