Refactor: Articles list view models
authorDa Risk <da_risk@geekorum.com>
Mon, 10 Dec 2018 14:39:15 -0800
changeset 32 140ab24f166b
parent 31 c048fd6ba8fa
child 33 67a8d23e6fc3
Refactor: Articles list view models
app/src/main/java/com/geekorum/ttrss/articles_list/ActivityViewModel.kt
app/src/main/java/com/geekorum/ttrss/articles_list/ArticleListActivity.kt
app/src/main/java/com/geekorum/ttrss/articles_list/ArticlesListFragment.java
app/src/main/java/com/geekorum/ttrss/articles_list/FeedListFragment.java
app/src/main/java/com/geekorum/ttrss/articles_list/FeedsRepository.kt
app/src/main/java/com/geekorum/ttrss/articles_list/FragmentViewModel.java
app/src/main/java/com/geekorum/ttrss/articles_list/di.kt
--- a/app/src/main/java/com/geekorum/ttrss/articles_list/ActivityViewModel.kt	Fri Dec 07 16:52:21 2018 -0800
+++ b/app/src/main/java/com/geekorum/ttrss/articles_list/ActivityViewModel.kt	Mon Dec 10 14:39:15 2018 -0800
@@ -28,9 +28,11 @@
 import com.geekorum.geekdroid.accounts.SyncInProgressLiveData
 import com.geekorum.geekdroid.app.lifecycle.EmptyEvent
 import com.geekorum.geekdroid.app.lifecycle.Event
+import com.geekorum.ttrss.BackgroundJobManager
 import com.geekorum.ttrss.data.Article
 import com.geekorum.ttrss.data.Feed
 import com.geekorum.ttrss.providers.ArticlesContract
+import javax.inject.Inject
 import com.geekorum.geekdroid.app.lifecycle.EmptyEvent.Companion.makeEmptyEvent as RefreshEvent
 import com.geekorum.geekdroid.app.lifecycle.EmptyEvent.Companion.makeEmptyEvent as SearchClosedEvent
 import com.geekorum.geekdroid.app.lifecycle.EmptyEvent.Companion.makeEmptyEvent as SearchOpenedEvent
@@ -39,12 +41,15 @@
 /**
  * [ViewModel] for the [ArticleListActivity]
  */
-class ActivityViewModel : ViewModel() {
+class ActivityViewModel @Inject constructor(
+    private val feedsRepository: FeedsRepository,
+    private val backgroundJobManager: BackgroundJobManager
+) : ViewModel() {
     private val account = MutableLiveData<Account>()
-    private val _selectedFeed = MutableLiveData<Feed>()
-    val selectedFeed: LiveData<Feed> = _selectedFeed
-    private val _refreshEvent = MutableLiveData<EmptyEvent>()
-    val refreshEvent: LiveData<EmptyEvent> = _refreshEvent
+    private val _selectedFeed = MutableLiveData<Long>()
+    val selectedFeed: LiveData<Feed> = Transformations.switchMap(_selectedFeed) {
+        feedsRepository.getFeedById(it)
+    }
     private val _articleSelectedEvent = MutableLiveData<Event<ArticleSelectedParameters>>()
     val articleSelectedEvent: LiveData<Event<ArticleSelectedParameters>> = _articleSelectedEvent
 
@@ -65,12 +70,17 @@
         this.account.value = account
     }
 
-    fun setSelectedFeed(feed: Feed) {
-        _selectedFeed.value = feed
+    fun setSelectedFeed(id: Long) {
+        _selectedFeed.value = id
     }
 
     fun refresh() {
-        _refreshEvent.value = RefreshEvent()
+        val feed = selectedFeed.value
+        if (feed != null) {
+            backgroundJobManager.refreshFeed(account.value, feed.id)
+        } else {
+            backgroundJobManager.refresh(account.value)
+        }
     }
 
     fun displayArticle(position: Int, article: Article) {
@@ -89,7 +99,7 @@
         _searchQuery.value = query
     }
 
-    class ArticleSelectedParameters internal constructor(val position: Int, val article: Article)
+    data class ArticleSelectedParameters(val position: Int, val article: Article)
 
     @Suppress("FunctionName")
     private fun ArticleSelectedEvent(position: Int, article: Article) =
--- a/app/src/main/java/com/geekorum/ttrss/articles_list/ArticleListActivity.kt	Fri Dec 07 16:52:21 2018 -0800
+++ b/app/src/main/java/com/geekorum/ttrss/articles_list/ArticleListActivity.kt	Mon Dec 10 14:39:15 2018 -0800
@@ -65,6 +65,7 @@
         private const val FRAGMENT_ARTICLES_LIST = "articles_list"
         private const val FRAGMENT_BACKSTACK_SEARCH = "search"
         private const val FRAGMENT_FEEDS_LIST = "feeds_list"
+        private const val STATE_FEED_ID = "feed_id"
     }
 
     /**
@@ -95,11 +96,11 @@
         setupPeriodicJobs()
         PreferenceManager.setDefaultValues(this, R.xml.pref_general, false)
 
-        activityViewModel = ViewModelProviders.of(this).get()
+        activityViewModel = ViewModelProviders.of(this, viewModelFactory).get()
         activityViewModel.selectedFeed.observe(this, Observer<Feed> { onFeedSelected(it) })
 
-        activityViewModel.articleSelectedEvent.observe(this, EventObserver { parameters ->
-            onArticleSelected(parameters.position, parameters.article)
+        activityViewModel.articleSelectedEvent.observe(this, EventObserver { (position, article) ->
+            onArticleSelected(position, article)
         })
 
         activityViewModel.searchOpenedEvent.observe(this, EventObserver {
@@ -145,15 +146,14 @@
             supportFragmentManager.transaction {
                 replace(R.id.start_pane_layout, feedListFragment, FRAGMENT_FEEDS_LIST)
             }
-            val feed = Feed.createVirtualFeedForId(Feed.FEED_ID_ALL_ARTICLES)
-            activityViewModel.setSelectedFeed(feed)
         }
+        val feedId = savedInstanceState?.getLong(STATE_FEED_ID) ?: Feed.FEED_ID_ALL_ARTICLES
+        activityViewModel.setSelectedFeed(feedId)
         setupToolbar()
     }
 
     private fun setupToolbar() {
         val toolbar = binding.toolbar.toolbar
-        toolbar.title = title
         setupSearch()
 
         if (!twoPane) {
@@ -229,6 +229,11 @@
         actionBarDrawerToggle?.onConfigurationChanged(newConfig)
     }
 
+    override fun onSaveInstanceState(outState: Bundle) {
+        super.onSaveInstanceState(outState)
+        outState.putLong(STATE_FEED_ID, activityViewModel.selectedFeed.value?.id ?: Feed.FEED_ID_ALL_ARTICLES)
+    }
+
     private fun onArticleSelected(position: Int, item: Article) {
         val articleUri = ContentUris.withAppendedId(ArticlesContract.Article.CONTENT_URI, item.id)
         if (twoPane) {
--- a/app/src/main/java/com/geekorum/ttrss/articles_list/ArticlesListFragment.java	Fri Dec 07 16:52:21 2018 -0800
+++ b/app/src/main/java/com/geekorum/ttrss/articles_list/ArticlesListFragment.java	Mon Dec 10 14:39:15 2018 -0800
@@ -120,11 +120,6 @@
         activityViewModel = ViewModelProviders.of(requireActivity()).get(ActivityViewModel.class);
         binding.setActivityViewModel(activityViewModel);
         binding.setFragmentViewModel(fragmentViewModel);
-        activityViewModel.getRefreshEvent().observe(this, event -> {
-            if (event.getContentIfNotHandled() != null) {
-                fragmentViewModel.refresh();
-            }
-        });
     }
 
     private void updateSetUnreadSnackbar(Integer nbArticles) {
--- a/app/src/main/java/com/geekorum/ttrss/articles_list/FeedListFragment.java	Fri Dec 07 16:52:21 2018 -0800
+++ b/app/src/main/java/com/geekorum/ttrss/articles_list/FeedListFragment.java	Mon Dec 10 14:39:15 2018 -0800
@@ -237,8 +237,9 @@
 
         // find feed
         for (Feed feed : currentFeeds) {
-            if (feed.getId() == item.getItemId()) {
-                activityViewModel.setSelectedFeed(feed);
+            long feedId = feed.getId();
+            if (feedId == item.getItemId()) {
+                activityViewModel.setSelectedFeed(feedId);
                 return true;
             }
         }
@@ -269,7 +270,7 @@
                     feed.setId(category.getId());
                     feed.setTitle(category.getTitle());
                     // TODO is cat = true);
-                    activityViewModel.setSelectedFeed(feed);
+//                    activityViewModel.setSelectedFeed(feed);
                 } else {
                     displayFeedCategory(category);
                 }
--- a/app/src/main/java/com/geekorum/ttrss/articles_list/FeedsRepository.kt	Fri Dec 07 16:52:21 2018 -0800
+++ b/app/src/main/java/com/geekorum/ttrss/articles_list/FeedsRepository.kt	Mon Dec 10 14:39:15 2018 -0800
@@ -22,6 +22,7 @@
 
 import android.util.Log
 import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.Transformations
 import com.geekorum.ttrss.data.Category
 import com.geekorum.ttrss.data.Feed
@@ -67,7 +68,14 @@
             return feedsDao.allUnreadCategories
         }
 
-    fun getFeedById(feedId: Long): LiveData<Feed> = feedsDao.getFeedById(feedId)
+    fun getFeedById(feedId: Long): LiveData<Feed> {
+        return when {
+            Feed.isVirtualFeed(feedId) -> MutableLiveData<Feed>().apply {
+                value = Feed.createVirtualFeedForId(feedId)
+            }
+            else -> feedsDao.getFeedById(feedId)
+        }
+    }
 
     private fun addSpecialFeeds(feeds: List<Feed>): List<Feed> {
         // add special feeds
--- a/app/src/main/java/com/geekorum/ttrss/articles_list/FragmentViewModel.java	Fri Dec 07 16:52:21 2018 -0800
+++ b/app/src/main/java/com/geekorum/ttrss/articles_list/FragmentViewModel.java	Mon Dec 10 14:39:15 2018 -0800
@@ -92,13 +92,7 @@
 
     private LiveData<Feed> getFeed() {
         if (feed == null) {
-            feed = Transformations.switchMap(feedId, id -> {
-                        if (Feed.isVirtualFeed(id)) {
-                            return createFeedLivedata(Feed.createVirtualFeedForId(id));
-                        }
-                        return feedsRepository.getFeedById(id);
-                    }
-            );
+            feed = Transformations.switchMap(feedId, id -> feedsRepository.getFeedById(id));
         }
         return feed;
     }
--- a/app/src/main/java/com/geekorum/ttrss/articles_list/di.kt	Fri Dec 07 16:52:21 2018 -0800
+++ b/app/src/main/java/com/geekorum/ttrss/articles_list/di.kt	Mon Dec 10 14:39:15 2018 -0800
@@ -55,6 +55,8 @@
         com.geekorum.ttrss.articles_list.FragmentsInjectorModule::class,
         com.geekorum.ttrss.article_details.FragmentsInjectorModule::class,
         com.geekorum.ttrss.articles_list.search.FragmentsInjectorModule::class,
+        ActivityViewModelModule::class,
+        TinyrssApiModule::class,
         NetworkLoginModule::class,
         SelectedAccountModule::class])
     @PerAccount
@@ -68,14 +70,10 @@
 @Module
 abstract class FragmentsInjectorModule {
 
-    @ContributesAndroidInjector(modules = [
-        ViewModelModule::class,
-        TinyrssApiModule::class])
+    @ContributesAndroidInjector(modules = [ViewModelModule::class])
     internal abstract fun contributesArticleListFragmentInjector(): ArticlesListFragment
 
-    @ContributesAndroidInjector(modules = [
-        ViewModelModule::class,
-        TinyrssApiModule::class])
+    @ContributesAndroidInjector(modules = [ViewModelModule::class])
     internal abstract fun contributesFeedListFragmentInjector(): FeedListFragment
 
 }
@@ -96,6 +94,15 @@
 }
 
 @Module
+private abstract class ActivityViewModelModule{
+    @Binds
+    @IntoMap
+    @ClassKey(ActivityViewModel::class)
+    abstract fun getActivityViewModel(activityViewModel: ActivityViewModel): ViewModel
+
+}
+
+@Module
 internal class SelectedAccountModule {
 
     @Provides