title: How to observe data generated from custom surface view
body: <p>I'm setting up room database in my application and I want to get data from user, who is drawing on custom surface view.</p>
  
  <p>App is running on Android 9, using MVVM pattern, I tried app without Room and it was working properly. After implementing Room, app don't observe data changes anymore. I used <a href="https://codelabs.developers.google.com/codelabs/android-room-with-a-view-kotlin/#0" rel="nofollow noreferrer" title="Android Room with a View - Kotlin">google codelabs</a> as template for my app. User is drawing nodes of graph on surface view by clicking on view and I want to store data of place(node) in database.</p>
  
  <p>Place:</p>
  
  <pre><code>@Entity(tableName = "places")
  data class Place(
          @Embedded
          var mPosition: Point,
  
          @PrimaryKey(autoGenerate = false)
          @ColumnInfo(name = "place_id")
          var mID: Int = -1,
  
          @ColumnInfo(name = "name")
          override var mName: String = "",
  
          @ColumnInfo(name = "tokens")
          var mTokens: Int = 0
  ) : Node() {
  
      override fun isValid(): Boolean {
          return mID == -1 &amp;&amp; mPosition.x != 0f &amp;&amp; mPosition.y != 0f &amp;&amp; mTokens &gt;= 0
      }
  }
  </code></pre>
  
  <p>PlaceDao:</p>
  
  <pre><code>@Dao
  interface PlaceDao {
  
      @Insert
      fun addPlace(place: Place)
  
      @Query("SELECT * FROM places ORDER BY place_id ASC")
      fun getPlaces(): LiveData&lt;List&lt;Place&gt;&gt;
      ...
  }
  </code></pre>
  
  <p>Database:</p>
  
  <pre><code>@Database(entities = [Place::class, Transition::class, Arc::class], version = 1)
  @TypeConverters(Converter::class)
  abstract class AppRoomDatabase : RoomDatabase() {
  
      abstract fun placeDao(): PlaceDao
  
  companion object {
          @Volatile
          private var INSTANCE: AppRoomDatabase? = null
  
          fun getDatabase(
                  context: Context,
                  scope: CoroutineScope
          ): AppRoomDatabase {
              return INSTANCE ?: synchronized(this) {
                  val instance = Room.databaseBuilder(
                          context.applicationContext,
                          AppRoomDatabase::class.java,
                          "word_database"
                  )
                          .fallbackToDestructiveMigration()
                          .addCallback(AppDatabaseCallback(scope))
                          .build()
                  INSTANCE = instance
                  instance
              }
          }
          private class AppDatabaseCallback(
                  private val scope: CoroutineScope
          ) : RoomDatabase.Callback() {
              override fun onOpen(db: SupportSQLiteDatabase) {
                  super.onOpen(db)
                  INSTANCE?.let { database -&gt;
                      scope.launch(Dispatchers.IO) {
                          populateDatabase(database.placeDao(),database.transitionDao(),database.arcDao())
                      }
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p>Repository:</p>
  
  <pre><code>class NetRepositoryImpl(
          private val placeDao: PlaceDao,
          private val transitionDao: TransitionDao,
          private val arcDao: ArcDao
  ) : NetRepository {
      @WorkerThread
      override suspend fun addPlace(place: Place) {
          placeDao.addPlace(place)
      }
  
      override fun getPlaces() = placeDao.getPlaces()
  }
  </code></pre>
  
  <p>ViewModel:</p>
  
  <pre><code>class NetViewModel(application: Application) : AndroidViewModel(application) {
  
      private var parentJob = Job()
      private val coroutineContext: CoroutineContext
          get() = parentJob + Dispatchers.Main
      private val scope = CoroutineScope(coroutineContext)
  
      private val netRepository: NetRepositoryImpl
  
      val allPlaces: LiveData&lt;List&lt;Place&gt;&gt;
      ...
  
  init {
          val placeDao = AppRoomDatabase.getDatabase(application, scope).placeDao()
      ...
      netRepository = NetRepositoryImpl(placeDao, transitionDao, arcDao)       
      allPlaces = netRepository.getPlaces()
      ...
  }
  
  fun addPlace(place: Place) {
          if (place.isValid())
              scope.launch(Dispatchers.IO) { netRepository.addPlace(place) }
      }
  </code></pre>
  
  <p>Activity:</p>
  
  <pre><code>class EditorActivity : FragmentActivity() {
      private lateinit var viewModel: NetViewModel
  
      override fun onCreate(savedInstanceState: Bundle?) {
          ...
  
          viewModel = ViewModelProviders.of(this).get(NetViewModel::class.java)
  
          viewModel.apply {
              allPlaces.observe(this@EditorActivity, Observer { places -&gt;
                  editorDrawer.mPlaces = places
                  Log.d("Editor activity", "Places observed")
              })
          ...
          editorDrawer.setOnTouchListener { v, event -&gt;
              when (event?.action) {
                  MotionEvent.ACTION_DOWN -&gt; {
              ...
              viewModel.addPlace(Point(event.x, event.y))
              ...
              }
          }
          ...
  }
  </code></pre>
  
  <p>editorDrawer is custom surface view in activity layout.</p>
  
  <p>When user clicks on surface view I expect to create new Place and store it in database, then draw it on surface view when data is changed, new instance of place is created but not stored and no changes are observed so no place is drawn. I can find in console log</p>
  
  <pre><code>"Places observed" 
  </code></pre>
  
  <p>only on app startup, like if data don't change at all...</p>