π App Introduction: News reader app with personalized content delivery and offline storage capability
π Duration: March 15, 2021 ~ June 30, 2021 (3.5 months)
π± Platform: Native Android app
π’ Company: Desoft (Cubaβs national software development company)
π₯ Team Size: 1 developer
πΌ Role: UI/UX design and complete Android app development
π οΈ Key Technologies: Android Kotlin Coroutines MVVM Room Retrofit Moshi Navigation Material Design Glide Lottie ViewBinding
π GitHub: daehan-lim/cubadebate-app
  
  
  
  
βββ database/                        # Local database related classes
β   βββ CubadebateDatabase.kt        # Room database main class
β   βββ converters/                  # Data type converters
β   βββ dao/                         # Data access objects
β   β   βββ PostDao.kt               # Post-related data access
β   β   βββ RecentCategoryDao.kt     # Recent category data access
β   β   βββ TagDao.kt                # Tag-related data access
β   βββ model/                       # Database entity models
β       βββ post/                    # Post-related entities
β       β   βββ DatabasePost.kt      # Post main entity
β       β   βββ DatabaseCategory.kt  # Category entity
β       β   βββ ...(other post entities)
β       βββ savedpost/               # Saved post entities
β       β   βββ SavedPost.kt         # Saved post main entity
β       β   βββ SavedCategory.kt     # Saved post category
β       β   βββ ...(other saved post entities)
β       βββ ...(other entities)
β
βββ model/                           # Data model classes
β   βββ api/                         # API response models
β   β   βββ comment/                 # Comment API models
β   β   β   βββ Content.kt           # Comment content
β   β   β   βββ ResponseComment.kt   # Comment response model
β   β   βββ post/                    # Post API models
β   β   β   βββ NetworkPost.kt       # Network post model
β   β   β   βββ ...(other API models)
β   βββ categories/                  # Category-related models
β   β   βββ MyCategoriesGridViewItem.kt
β   βββ comment/                     # Comment domain models
β   β   βββ Comment.kt               # Comment information
β   βββ post/                        # Post domain models
β       βββ Post.kt                  # Post main model
β       βββ Category.kt              # Category model
β       βββ ...(other post models)
β
βββ network/                         # Network communication classes
β   βββ CubadebateApiService.kt      # Retrofit API service interface
β
βββ repository/                      # Data repository (Repository pattern)
β   βββ PostRepository.kt            # Post data management
β   βββ RecentCategoryRepository.kt  # Recent category data management
β   βββ TagRepository.kt             # Tag data management
β
βββ ui/                              # User interface classes
β   βββ CoroutineBaseViewModel.kt    # Coroutine-based base view model
β   βββ PostsViewModel.kt            # Common post view model
β   βββ HeadingsAdapter.kt           # Post list adapter
β   βββ EndlessRecyclerViewScrollListener.kt  # Infinite scroll listener
β   βββ main/                        # Main screen classes
β   β   βββ MainActivity.kt          # Main activity
β   β   βββ MainActivityViewModel.kt # Main activity view model
β   βββ categories/                  # Category screens
β   β   βββ BaseCategoryFragment.kt  # Category base fragment
β   β   βββ HomeFragment.kt          # Home fragment
β   βββ details/                     # Post detail screen
β   βββ comments/                    # Comment-related screens
β   β   βββ CommentsActivity.kt      # Comments activity
β   β   βββ CommentsFragment.kt      # Comments fragment
β   β   βββ RepliesFragment.kt       # Comment replies fragment
β   β   βββ ...(ViewModels and other classes)
β   βββ search/                      # Search screens
β   βββ saved/                       # Saved posts screen
β   βββ forme/                       # Personalized recommendation screen
β   β   βββ ForMeFragment.kt         # Recommendation main fragment
β   β   βββ MyCategoriesFragment.kt  # My categories fragment
β   β   βββ MyTopicsFragment.kt      # My topics fragment
β   β   βββ ...(ViewModels and other classes)
β   β
β   βββ headingspertag/              # Posts by tag screen
β   βββ subscription/                # Subscription screens
β   βββ settings/                    # Settings screens
β       βββ categories/              # Category management
β       βββ topics/                  # Topic management
β
βββ util/                            # Utility classes and helper functions
    βββ ActivityUtils.kt             # Activity utilities
    βββ BindingUtils.kt              # Data binding utilities
    βββ MappingUtils.kt              # Data mapping utilities
    βββ PostUtils.kt                 # Post utilities
    βββ PreferenceManager.kt         # Settings management utilities
    βββ Util.kt                      # General utility functions
1. Offline Storage Architecture Selection
Requirements
Users needed reliable offline access to news articles even in unstable network environments
Decision
Implemented robust offline storage using Room Database
@Entity(tableName = "posts")
data class DatabasePost(
    @PrimaryKey val id: Long,
    val title: String,
    val content: String,
    val imageUrl: String?,
    val publishedDate: String,
    val isSaved: Boolean = false
)
2. MVVM Architecture Implementation
Requirements
Needed systematic management of complex news data flows and UI states while efficiently integrating network and local data sources
Decision
Built layered architecture combining MVVM with Repository pattern
class PostRepository(private val database: CubadebateDatabase) {
    suspend fun getPosts(categoryId: Long?): MutableList<Post> {
        return withContext(Dispatchers.IO) {
            try {
                // Attempt to fetch latest data from network
                val networkPosts = when(categoryId) {
                    null -> CubadebateApi.retrofitService.getPostsAsync()
                    else -> CubadebateApi.retrofitService.getPostsByCategoryAsync(categoryId)
                }.await()
                
                // Save to local DB and return
                networkPosts.map { it.mapToPost() }
            } catch (e: Exception) {
                // Return local data on network failure
                getPostsFromDb(categoryId)
            }
        }
    }
}
1. User-Centric Content Discovery Enhancement
Problem
Users found it difficult to freely explore or subscribe to news on topics of interest through the existing website, with no way to customize content based on user preferences
RecyclerView and Room Database to aggregate news from user-selected topics