Search code examples
androidkotlinfilelocal-storageandroid-jetpack-compose

Where to put the code that creates local files in android?


I'm trying to create an app (using Kotlin with Jetpack Compose) that can save files to internal storage, but I don't know what is the best place to put for example this code:

fun deleteFile(context: Context, filePath: String): Boolean {
    
    val path = context.filesDir
    val file = File(path, filePath)

    if (!file.exists()) return false
    
    return file.deleteRecursively()
}

Since I need the context to handling files the code must be in the UI layer right? But isn't it a business code? If is business code I can't put it in the data layer because I need context, passing the context to the viewModel is also not good, so where?


Solution

  • Typically, in an Android app architecture that follows the recommended practices, you would have separate layers such as UI layer (composed of activities/fragments and Jetpack Compose), ViewModel layer, and Data layer (including repositories and data sources). To handle file operations, you can introduce a repository pattern.

    The FileRepository class acts as an intermediary between the ViewModel and the file system, utilizing the application context to delete files from internal storage.

    class FileRepository(private val application: Application) {
    
        fun deleteFile(filePath: String): Boolean {
            val path = application.filesDir
            val file = File(path, filePath)
    
            if (!file.exists()) return false
    
            return file.deleteRecursively()
        }
    }
    

    The MyViewModel class extends AndroidViewModel and holds an instance of the FileRepository. It serves as a bridge between the UI layer and the file handling logic,

    class MyViewModel(application: Application) : AndroidViewModel(application) {
    
        private val fileRepository by lazy { FileRepository(application) }
        
        fun deleteFile(filePath: String): Boolean {
            return fileRepository.deleteFile(filePath)
        }
    }
    

    Example usage

    @Composable
    fun Example(myViewModel: MyViewModel = viewModel()) {
        // UI
    }
    

    The function takes an instance of MyViewModel as a parameter, with a default value obtained using the viewModel() function. Inside the function, you would define the UI elements and layout specific to this component.