Skip to content

Commit 195933e

Browse files
committed
Replace connectivity EventBus with LiveData
Drop the ConnectionChangeEvent-over-EventBus delivery introduced with NetworkConnectionMonitor and expose the connected state as a LiveData<Boolean> that subscribers observe via their lifecycle owner. Removes EventBus entirely from SuggestionActivity and BlogPreferencesActivity; the other subscribers keep EventBus for unrelated events.
1 parent 5f85a77 commit 195933e

8 files changed

Lines changed: 59 additions & 60 deletions

File tree

WordPress/src/main/java/org/wordpress/android/networking/NetworkConnectionMonitor.kt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import android.net.NetworkCapabilities
77
import android.net.NetworkRequest
88
import android.os.Handler
99
import android.os.HandlerThread
10-
import org.greenrobot.eventbus.EventBus
10+
import androidx.lifecycle.LiveData
11+
import androidx.lifecycle.MutableLiveData
1112
import org.wordpress.android.util.AppLog
1213
import org.wordpress.android.util.AppLog.T
1314
import javax.inject.Inject
@@ -18,9 +19,9 @@ import javax.inject.Singleton
1819
*
1920
* Uses [ConnectivityManager.NetworkCallback] registered on a background [HandlerThread] rather than the
2021
* deprecated CONNECTIVITY_ACTION broadcast. Because a NetworkCallback is not a broadcast it is not subject to
21-
* background-broadcast ANR timeouts, and all connectivity work runs off the main thread. A
22-
* [ConnectionChangeEvent] is posted on EventBus whenever the connected state changes; EventBus marshals the
23-
* `onEventMainThread` subscribers back onto the main thread.
22+
* background-broadcast ANR timeouts, and all connectivity work runs off the main thread. The connected state
23+
* is exposed as [isConnected]; observers are notified on the main thread via LiveData whenever the connected
24+
* state changes.
2425
*
2526
* Connectivity is tracked as the set of currently-available internet-capable networks rather than a single
2627
* network. During a handover (e.g. Wi-Fi -> cellular) where the replacement is already up, it is added before
@@ -34,7 +35,8 @@ class NetworkConnectionMonitor @Inject constructor() {
3435
private var isFirstCallback = true
3536
private val availableNetworks = mutableSetOf<Network>()
3637

37-
class ConnectionChangeEvent(val isConnected: Boolean)
38+
private val _isConnected = MutableLiveData<Boolean>()
39+
val isConnected: LiveData<Boolean> = _isConnected
3840

3941
@Synchronized
4042
fun start(context: Context) {
@@ -61,15 +63,15 @@ class NetworkConnectionMonitor @Inject constructor() {
6163
}
6264

6365
/**
64-
* Called on the monitor's background thread. Posts a [ConnectionChangeEvent] on the first callback and
65-
* whenever the connected state actually changes, so subscribers aren't spammed while connectivity churns.
66+
* Called on the monitor's background thread. Updates [isConnected] on the first callback and whenever the
67+
* connected state actually changes, so observers aren't spammed while connectivity churns.
6668
*/
6769
private fun onConnectivityChanged(isConnected: Boolean) {
6870
if (isFirstCallback || isConnected != wasConnected) {
6971
isFirstCallback = false
7072
wasConnected = isConnected
7173
AppLog.i(T.UTILS, "Connection status changed, isConnected=$isConnected")
72-
EventBus.getDefault().post(ConnectionChangeEvent(isConnected))
74+
_isConnected.postValue(isConnected)
7375
}
7476
}
7577
}

WordPress/src/main/java/org/wordpress/android/ui/main/WPMainActivity.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,8 @@ public class WPMainActivity extends BaseAppCompatActivity implements
279279

280280
@Inject WpAppNotifierHandler mWpAppNotifierHandler;
281281

282+
@Inject NetworkConnectionMonitor mNetworkConnectionMonitor;
283+
282284
/*
283285
* fragments implement this if their contents can be scrolled, called when user
284286
* requests to scroll to the top
@@ -414,6 +416,8 @@ && getIntent().getExtras().getBoolean(ARG_CONTINUE_JETPACK_CONNECT, false)) {
414416
mDispatcher.register(this);
415417
EventBus.getDefault().register(this);
416418

419+
mNetworkConnectionMonitor.isConnected().observe(this, this::updateConnectionBar);
420+
417421
if (authTokenToSet != null) {
418422
// Save Token to the AccountStore. This will trigger a onAuthenticationChanged.
419423
UpdateTokenPayload payload = new UpdateTokenPayload(authTokenToSet);
@@ -1488,12 +1492,6 @@ public void onEventMainThread(NotificationEvents.NotificationsUnseenStatus event
14881492
if (mBottomNav != null) mBottomNav.showNoteBadge(event.hasUnseenNotes);
14891493
}
14901494

1491-
@SuppressWarnings("unused")
1492-
@Subscribe(threadMode = ThreadMode.MAIN)
1493-
public void onEventMainThread(NetworkConnectionMonitor.ConnectionChangeEvent event) {
1494-
updateConnectionBar(event.isConnected());
1495-
}
1496-
14971495
private void checkConnection() {
14981496
updateConnectionBar(NetworkUtils.isNetworkAvailable(this));
14991497
}

WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ import org.wordpress.android.fluxc.store.bloggingprompts.BloggingPromptsStore
119119
import org.wordpress.android.fluxc.tools.FluxCImageLoader
120120
import org.wordpress.android.imageeditor.preview.PreviewImageFragment
121121
import org.wordpress.android.imageeditor.preview.PreviewImageFragment.Companion.EditImageData.InputData
122-
import org.wordpress.android.networking.NetworkConnectionMonitor.ConnectionChangeEvent
122+
import org.wordpress.android.networking.NetworkConnectionMonitor
123123
import org.wordpress.android.support.ZendeskHelper
124124
import org.wordpress.android.ui.ActivityId
125125
import org.wordpress.android.ui.ActivityLauncher
@@ -412,6 +412,8 @@ class EditPostActivity : BaseAppCompatActivity(), EditorFragmentActivity, Editor
412412
@Inject lateinit var storageUtilsViewModel: StorageUtilsViewModel
413413
@Inject lateinit var editorBloggingPromptsViewModel: EditorBloggingPromptsViewModel
414414
@Inject lateinit var editorJetpackSocialViewModel: EditorJetpackSocialViewModel
415+
416+
@Inject lateinit var networkConnectionMonitor: NetworkConnectionMonitor
415417
private lateinit var editPostNavigationViewModel: EditPostNavigationViewModel
416418
private lateinit var editPostSettingsViewModel: EditPostSettingsViewModel
417419
private lateinit var prepublishingViewModel: PrepublishingViewModel
@@ -558,6 +560,9 @@ class EditPostActivity : BaseAppCompatActivity(), EditorFragmentActivity, Editor
558560
}
559561
editorMedia.start(siteModel, this)
560562
startObserving()
563+
networkConnectionMonitor.isConnected.observe(this) { connected ->
564+
(editorFragment as? GutenbergNetworkConnectionListener)?.onConnectionStatusChange(connected)
565+
}
561566
editorFragment?.let {
562567
hasSetPostContent = true
563568
it.setImageLoader(imageLoader)
@@ -3858,11 +3863,6 @@ class EditPostActivity : BaseAppCompatActivity(), EditorFragmentActivity, Editor
38583863
}
38593864
}
38603865

3861-
@Subscribe(threadMode = ThreadMode.MAIN)
3862-
fun onEventMainThread(event: ConnectionChangeEvent) {
3863-
(editorFragment as? GutenbergNetworkConnectionListener)?.onConnectionStatusChange(event.isConnected)
3864-
}
3865-
38663866
private fun refreshEditorTheme() {
38673867
val payload = FetchEditorThemePayload(siteModel, gssEnabled = true)
38683868
dispatcher.dispatch(EditorThemeActionBuilder.newFetchEditorThemeAction(payload))

WordPress/src/main/java/org/wordpress/android/ui/prefs/BlogPreferencesActivity.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import androidx.appcompat.widget.Toolbar;
1111

1212
import org.apache.commons.text.StringEscapeUtils;
13-
import org.greenrobot.eventbus.EventBus;
1413
import org.greenrobot.eventbus.Subscribe;
1514
import org.greenrobot.eventbus.ThreadMode;
1615
import org.wordpress.android.R;
@@ -42,6 +41,9 @@ public class BlogPreferencesActivity extends BaseAppCompatActivity {
4241
@Inject AccountStore mAccountStore;
4342
@Inject SiteStore mSiteStore;
4443
@Inject Dispatcher mDispatcher;
44+
@Inject NetworkConnectionMonitor mNetworkConnectionMonitor;
45+
46+
private Boolean mLastConnected;
4547

4648
@Override
4749
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -84,19 +86,19 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
8486
.replace(R.id.fragment_container, siteSettingsFragment, KEY_SETTINGS_FRAGMENT)
8587
.commit();
8688
}
89+
90+
mNetworkConnectionMonitor.isConnected().observe(this, this::onConnectionChanged);
8791
}
8892

8993
@Override
9094
protected void onStart() {
9195
super.onStart();
92-
EventBus.getDefault().register(this);
9396
mDispatcher.register(this);
9497
}
9598

9699
@Override
97100
protected void onStop() {
98101
mDispatcher.unregister(this);
99-
EventBus.getDefault().unregister(this);
100102
super.onStop();
101103
}
102104

@@ -117,21 +119,22 @@ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
117119
return super.onOptionsItemSelected(item);
118120
}
119121

120-
@SuppressWarnings("unused")
121-
@Subscribe(threadMode = ThreadMode.MAIN)
122-
public void onEventMainThread(NetworkConnectionMonitor.ConnectionChangeEvent event) {
122+
private void onConnectionChanged(boolean connected) {
123123
SiteSettingsFragment siteSettingsFragment = getSettingsFragment();
124124
if (siteSettingsFragment != null) {
125-
if (!event.isConnected()) {
125+
// Toast only on a genuine transition to disconnected, so LiveData replay on re-foregrounding
126+
// doesn't spuriously toast.
127+
if (!connected && mLastConnected != null && mLastConnected) {
126128
ToastUtils.showToast(this, getString(R.string.site_settings_disconnected_toast), Duration.LONG);
127129
}
128-
siteSettingsFragment.setEditingEnabled(event.isConnected());
130+
siteSettingsFragment.setEditingEnabled(connected);
129131

130132
// TODO: add this back when delete blog is back
131133
// https://github.com/wordpress-mobile/WordPress-Android/commit/6a90e3fe46e24ee40abdc4a7f8f0db06f157900c
132134
// Checks for stats widgets that were synched with a blog that could be gone now.
133135
// StatsWidgetProvider.updateWidgetsOnLogout(this);
134136
}
137+
mLastConnected = connected;
135138
}
136139

137140
@SuppressWarnings("unused")

WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.kt

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ import org.wordpress.android.models.ReaderPost
6969
import org.wordpress.android.models.ReaderPostDiscoverData
7070
import org.wordpress.android.models.ReaderTag
7171
import org.wordpress.android.models.ReaderTagType
72-
import org.wordpress.android.networking.NetworkConnectionMonitor.ConnectionChangeEvent
72+
import org.wordpress.android.networking.NetworkConnectionMonitor
7373
import org.wordpress.android.ui.ActionableEmptyView
7474
import org.wordpress.android.ui.ActivityLauncher
7575
import org.wordpress.android.ui.EmptyViewMessageType
@@ -205,6 +205,11 @@ class ReaderPostListFragment : ViewPagerFragment(), OnPostSelectedListener, OnFo
205205
@Inject
206206
lateinit var displayUtilsWrapper: DisplayUtilsWrapper
207207

208+
@Inject
209+
lateinit var networkConnectionMonitor: NetworkConnectionMonitor
210+
211+
private var lastConnected: Boolean? = null
212+
208213
private var readerPostAdapter: ReaderPostAdapter? = null
209214
private var siteSearchAdapter: ReaderSiteSearchAdapter? = null
210215
private var suggestionAdapter: ReaderSearchSuggestionAdapter? = null
@@ -572,6 +577,15 @@ class ReaderPostListFragment : ViewPagerFragment(), OnPostSelectedListener, OnFo
572577
}
573578
}
574579
}
580+
581+
networkConnectionMonitor.isConnected.observe(viewLifecycleOwner) { connected ->
582+
// Only resubmit the search when connectivity actually transitions to connected, so LiveData replay
583+
// on re-foregrounding doesn't re-fire the search.
584+
if (connected && lastConnected != connected) {
585+
currentSearchQuery?.let { submitSearchQuery(it) }
586+
}
587+
lastConnected = connected
588+
}
575589
}
576590

577591
private fun toggleJetpackBannerIfEnabled(showIfEnabled: Boolean, animateOnScroll: Boolean) {
@@ -1370,15 +1384,6 @@ class ReaderPostListFragment : ViewPagerFragment(), OnPostSelectedListener, OnFo
13701384
dispatcher.dispatch(ReaderActionBuilder.newReaderSearchSitesAction(payload))
13711385
}
13721386

1373-
@Subscribe(threadMode = ThreadMode.MAIN)
1374-
fun onEventMainThread(event: ConnectionChangeEvent) {
1375-
if (event.isConnected) {
1376-
if (currentSearchQuery != null) {
1377-
submitSearchQuery(currentSearchQuery!!)
1378-
}
1379-
}
1380-
}
1381-
13821387
private fun submitSearchQuery(query: String) {
13831388
if (!isAdded) {
13841389
return

WordPress/src/main/java/org/wordpress/android/ui/suggestion/SuggestionActivity.kt

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,11 @@ import android.text.TextWatcher
1010
import android.view.KeyEvent
1111
import android.view.inputmethod.EditorInfo
1212
import androidx.activity.addCallback
13-
import org.greenrobot.eventbus.EventBus
14-
import org.greenrobot.eventbus.Subscribe
15-
import org.greenrobot.eventbus.ThreadMode
1613
import org.wordpress.android.R
1714
import org.wordpress.android.WordPress
1815
import org.wordpress.android.databinding.SuggestUsersActivityBinding
1916
import org.wordpress.android.fluxc.model.SiteModel
20-
import org.wordpress.android.networking.NetworkConnectionMonitor.ConnectionChangeEvent
17+
import org.wordpress.android.networking.NetworkConnectionMonitor
2118
import org.wordpress.android.ui.main.BaseAppCompatActivity
2219
import org.wordpress.android.ui.suggestion.FinishAttempt.NotExactlyOneAvailable
2320
import org.wordpress.android.ui.suggestion.FinishAttempt.OnlyOneAvailable
@@ -36,6 +33,9 @@ class SuggestionActivity : BaseAppCompatActivity() {
3633

3734
@Inject
3835
lateinit var viewModel: SuggestionViewModel
36+
37+
@Inject
38+
lateinit var networkConnectionMonitor: NetworkConnectionMonitor
3939
private lateinit var binding: SuggestUsersActivityBinding
4040

4141
override fun onCreate(savedInstanceState: Bundle?) {
@@ -178,6 +178,11 @@ class SuggestionActivity : BaseAppCompatActivity() {
178178

179179
updateEmptyView()
180180
})
181+
182+
networkConnectionMonitor.isConnected.observe(this) { connected ->
183+
viewModel.onConnectionChanged(connected)
184+
updateEmptyView()
185+
}
181186
}
182187

183188
private fun exitIfOnlyOneMatchingUser() {
@@ -250,23 +255,11 @@ class SuggestionActivity : BaseAppCompatActivity() {
250255

251256
override fun onResume() {
252257
super.onResume()
253-
EventBus.getDefault().register(this)
254258
if (binding.autocompleteText.isAttachedToWindow) {
255259
binding.autocompleteText.showDropDown()
256260
}
257261
}
258262

259-
override fun onPause() {
260-
EventBus.getDefault().unregister(this)
261-
super.onPause()
262-
}
263-
264-
@Subscribe(threadMode = ThreadMode.MAIN)
265-
fun onEventMainThread(event: ConnectionChangeEvent) {
266-
viewModel.onConnectionChanged(event)
267-
updateEmptyView()
268-
}
269-
270263
companion object {
271264
const val SELECTED_VALUE = "SELECTED_VALUE"
272265

WordPress/src/main/java/org/wordpress/android/ui/suggestion/SuggestionViewModel.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import androidx.lifecycle.ViewModel
66
import org.wordpress.android.R
77
import org.wordpress.android.analytics.AnalyticsTracker
88
import org.wordpress.android.fluxc.model.SiteModel
9-
import org.wordpress.android.networking.NetworkConnectionMonitor.ConnectionChangeEvent
109
import org.wordpress.android.ui.suggestion.FinishAttempt.NotExactlyOneAvailable
1110
import org.wordpress.android.ui.suggestion.FinishAttempt.OnlyOneAvailable
1211
import org.wordpress.android.ui.suggestion.SuggestionType.Users
@@ -59,8 +58,8 @@ class SuggestionViewModel @Inject constructor(
5958

6059
private fun supportsSuggestions(site: SiteModel): Boolean = SiteUtils.isAccessedViaWPComRest(site)
6160

62-
fun onConnectionChanged(event: ConnectionChangeEvent) {
63-
if (event.isConnected) {
61+
fun onConnectionChanged(isConnected: Boolean) {
62+
if (isConnected) {
6463
suggestionSource.refreshSuggestions()
6564
}
6665
}

WordPress/src/test/java/org/wordpress/android/ui/suggestion/SuggestionViewModelTest.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import org.mockito.kotlin.whenever
1818
import org.wordpress.android.R
1919
import org.wordpress.android.analytics.AnalyticsTracker
2020
import org.wordpress.android.fluxc.model.SiteModel
21-
import org.wordpress.android.networking.NetworkConnectionMonitor.ConnectionChangeEvent
2221
import org.wordpress.android.ui.suggestion.FinishAttempt.NotExactlyOneAvailable
2322
import org.wordpress.android.ui.suggestion.FinishAttempt.OnlyOneAvailable
2423
import org.wordpress.android.ui.suggestion.SuggestionType.Users
@@ -88,14 +87,14 @@ class SuggestionViewModelTest {
8887
@Test
8988
fun `onConnectionChanged not connected`() {
9089
initViewModel()
91-
viewModel.onConnectionChanged(ConnectionChangeEvent(false))
90+
viewModel.onConnectionChanged(false)
9291
verify(mockSuggestionSource, never()).refreshSuggestions()
9392
}
9493

9594
@Test
9695
fun `onConnectionChanged connected`() {
9796
initViewModel()
98-
viewModel.onConnectionChanged(ConnectionChangeEvent(true))
97+
viewModel.onConnectionChanged(true)
9998
verify(mockSuggestionSource).refreshSuggestions()
10099
}
101100

0 commit comments

Comments
 (0)