Save User State

Sep 10 2024 · Kotlin 1.9, Android 14, Android Studio Koala | 2024.1.1

Lesson 03: Read & Write Files

Read & Write Files in Internal Storage

Episode complete

Play next episode

Next

Heads up... You’re accessing parts of this content for free, with some sections shown as obfuscated text.

Heads up... You’re accessing parts of this content for free, with some sections shown as obfuscated text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

Creating Internal Notes

Open the starter project in the IDE, then build and run it. You’ll see a text with “No notes available” displayed on the home screen. This is because you still need to add notes. Tap the Create Note button to navigate to the Create Note screen. For now, you won’t be able to fill in the details and create a note. You’ll add this functionality in this lesson.

import android.content.Context
import com.kodeco.android.devscribe.data.local.NoteEntity
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.io.File
import java.io.IOException

class InternalNotesFileManager(
  private val context: Context
) {
  
  fun writeTextFile(note: NoteEntity) {
    val directory = File(context.filesDir, DIRECTORY_NAME)
    if (!directory.exists()) {
      directory.mkdirs()
    }
    val file = File(directory, "${note.title}.txt")
    try {
      file.outputStream().use { outputStream ->
        outputStream.write(Json.encodeToString(note).toByteArray())
      }
    } catch (e: IOException) {
      e.printStackTrace()
    }
  }

  companion object {
    const val DIRECTORY_NAME = "DevScribeNotesInternal"
  }
}
fun readTextFile(): List<NoteEntity> {
  val directory = File(context.filesDir, DIRECTORY_NAME)
  val noteFiles = directory.listFiles()?.filter { it.isFile && it.name.endsWith(".txt") }
  val notes = mutableListOf<NoteEntity>()
  noteFiles?.forEach { file ->
    try {
      val inputStream = FileInputStream(file)
      val content = inputStream.bufferedReader().use { it.readText() }
      notes.add(
        Json.decodeFromString(content)
      )
    } catch (e: IOException) {
      e.printStackTrace()
    }
  }
  return notes
}
val notesFileManagerModule = module {
  single { InternalNotesFileManager(androidContext()) }
}
val appModules = listOf(
  dataStoreModule,
  viewModelModule,
  notesFileManagerModule
)
val viewModelModule = module {
  viewModel { MainViewModel(get(), get()) }
}
class MainViewModel(
  private val dataStoreManager: DataStoreManager,
  private val internalNotesFileManager: InternalNotesFileManager
): ViewModel() {

// The rest of the code
}
fun handleCreateNoteEvents(event: CreateNoteEvents) {
  when(event) {
    is CreateNoteEvents.TitleChanged -> {
      _createNoteState.update {
        it.copy(title = event.title)
      }
    }
    is CreateNoteEvents.DescriptionChanged -> {
      _createNoteState.update {
        it.copy(description = event.description)
      }
    }
    is CreateNoteEvents.PriorityChanged -> {
      _createNoteState.update {
        it.copy(priority = event.priority)
      }
    }
    is CreateNoteEvents.CreateNote -> {
      if(createNoteState.value.isValid()) {
        viewModelScope.launch {
          val noteEntity = NoteEntity(
            title = createNoteState.value.title ?: "",
            description = createNoteState.value.description ?: "",
            priority = createNoteState.value.priority ?: "",
            timestamp = System.currentTimeMillis(),
            noteLocation = createNoteState.value.noteLocation ?: ""
          )
          when(noteEntity.noteLocation) {
            "Internal Storage" -> {
              internalNotesFileManager.writeTextFile(noteEntity)
            }
            else -> {
              // TODO: Implement other note locations
            }
          }
        }
      }
    }
    is CreateNoteEvents.NoteLocationChanged -> {
      _createNoteState.update {
        it.copy(noteLocation = event.noteLocation)
      }
    }
  }
}
private fun fetchNotes() {
  viewModelScope.launch {
    _notes.update {
      internalNotesFileManager.readTextFile()
    }
  }
}
init {
  fetchSelectedFilter()
  fetchNotes()
}
CreateNoteScreenContent(
  createNoteState = createNoteState,
  onTitleChange = { title ->
    viewModel.handleCreateNoteEvents(CreateNoteEvents.TitleChanged(title))
  },
  onDescriptionChange = { description ->
    viewModel.handleCreateNoteEvents(CreateNoteEvents.DescriptionChanged(description))
  },
  onPriorityChange = { priority ->
    viewModel.handleCreateNoteEvents(CreateNoteEvents.PriorityChanged(priority))
  },
  onCreateNote = {
    viewModel.handleCreateNoteEvents(CreateNoteEvents.CreateNote)
    navigateBack()
  },
  onNoteLocationChange = { noteLocation ->
    viewModel.handleCreateNoteEvents(CreateNoteEvents.NoteLocationChanged(noteLocation))
  }
)
See forum comments
Cinema mode Download course materials from Github
Previous: Instruction Next: Read & Write Files in External Storage