Fixed
Status Update
Comments
yb...@google.com <yb...@google.com>
ya...@google.com <ya...@google.com> #2
The problem is reproducible using support lib 26.1.0, this is the updated activity:
class LiveDataTestActivity : AppCompatActivity() {
private val myLiveData = MutableLiveData<Int>().apply { value = 0 }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val textView = TextView(this).apply {
text = "AAAA"
setOnClickListener {
val sendIntent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
type = "text/plain"
}
startActivityForResult(sendIntent, 123)
}
}
setContentView(textView)
myLiveData.observe(this, Observer<Int> {
textView.text = it.toString()
})
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
myLiveData.value = (myLiveData.value ?: 0) + 1
println("Value ${myLiveData.value}")
}
override fun onResume() {
super.onResume()
println("resume ${lifecycle.currentState}")
}
}
class LiveDataTestActivity : AppCompatActivity() {
private val myLiveData = MutableLiveData<Int>().apply { value = 0 }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val textView = TextView(this).apply {
text = "AAAA"
setOnClickListener {
val sendIntent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
type = "text/plain"
}
startActivityForResult(sendIntent, 123)
}
}
setContentView(textView)
myLiveData.observe(this, Observer<Int> {
textView.text = it.toString()
})
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
myLiveData.value = (myLiveData.value ?: 0) + 1
println("Value ${myLiveData.value}")
}
override fun onResume() {
super.onResume()
println("resume ${lifecycle.currentState}")
}
}
mm...@commonsware.com <mm...@commonsware.com> #3
thanks for the reports.
After further investigation:
good news, this is not a very serious bug, it recovers right after onResume. (also the bug does not happen in latest versions of the OS)
bad news, properly fixing it requires changes in the support library so it may not catch 1.0.0 release.
details:
Lifecycles moves state to CREATED when onSavedInstanceState is called. This is done because FragmentManager disables fragment transactions when onSavedInstanceState is called. Lifecycles API guaratees that you can run a fragment transaction inside an observer. This behavior is usually fine because onSavedInstanceState is always followed by onStop.
Turns out, this is not the case for API21..
things to do:
* make sure we have tests that fragments are handled properly and observers don't receive an unexpected STARTED event.
* in the next support lib version, make sure the state is set to at least STARTED when FragmentController#noteStateNotSaved is called.
After further investigation:
good news, this is not a very serious bug, it recovers right after onResume. (also the bug does not happen in latest versions of the OS)
bad news, properly fixing it requires changes in the support library so it may not catch 1.0.0 release.
details:
Lifecycles moves state to CREATED when onSavedInstanceState is called. This is done because FragmentManager disables fragment transactions when onSavedInstanceState is called. Lifecycles API guaratees that you can run a fragment transaction inside an observer. This behavior is usually fine because onSavedInstanceState is always followed by onStop.
Turns out, this is not the case for API21..
things to do:
* make sure we have tests that fragments are handled properly and observers don't receive an unexpected STARTED event.
* in the next support lib version, make sure the state is set to at least STARTED when FragmentController#noteStateNotSaved is called.
ya...@google.com <ya...@google.com> #4
Fabio, thanks for the bug report and example code. We have a fix in the works that will update the TextView on 5.0 (the problem actually existed on 6.0 and below) just like it should on 6.0.
However, note that on 6.0 and below your onResume method will continue to print "CREATED" as Yigit mentioned above.
Thanks again!
However, note that on 6.0 and below your onResume method will continue to print "CREATED" as Yigit mentioned above.
Thanks again!
mm...@commonsware.com <mm...@commonsware.com> #5
reopened. fix for live data is in but the greater fix to make lifecycles consistent is still not merged.
ya...@google.com <ya...@google.com> #6
Norm
Description
Version used: 1.0.0-alpha3
Devices/Android versions reproduced on: Nexus 5X (ODP3)
The implementation of FrameworkSQLiteOpenHelper does not close the actual SQLite database. The static OpenHelper class' close() method is:
@Override
public synchronized void close() {
super.close();
mWrappedDb = null;
}
(based on the code distributed along with the 1.0.0-alpha3 artifact)
AFAICT, there should be an mWrappedDb.close() in there, as I do not see anything else that will ever close that FrameworkSQLiteDatabase.
I am back to working on SafeRoom, my SQLCipher for Android implementation of the Support* classes. If I add close() to my SupportSQLiteHelper.Factory as shown above, I then run into a related crash:
E/AndroidRuntime: FATAL EXCEPTION: pool-1-thread-1
Process: com.commonsware.cwac.saferoom.test, PID: 9294
net.sqlcipher.database.SQLiteMisuseException: library routine called out of sequence: , while compiling: SELECT * FROM room_table_modification_log WHERE version > ? ORDER BY version ASC;
at net.sqlcipher.database.SQLiteCompiledSql.native_compile(Native Method)
at net.sqlcipher.database.SQLiteCompiledSql.compile(SQLiteCompiledSql.java:91)
at net.sqlcipher.database.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:64)
at net.sqlcipher.database.SQLiteProgram.<init>(SQLiteProgram.java:84)
at net.sqlcipher.database.SQLiteQuery.<init>(SQLiteQuery.java:49)
at net.sqlcipher.database.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:42)
at net.sqlcipher.database.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1820)
at com.commonsware.cwac.saferoom.Database.query(Database.java:176)
at com.commonsware.cwac.saferoom.Database.query(Database.java:145)
at android.arch.persistence.room.RoomDatabase.query(RoomDatabase.java:156)
at android.arch.persistence.room.InvalidationTracker$2.run(InvalidationTracker.java:354)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
This is stemming from InvalidationTracker, and it is occurring sometime after I call close() on the RoomDatabase. If I either do not close() the RoomDatabase or I do not close() the actual database, this crash does not appear. My best guess is that close() on RoomDatabase is not shutting down related InvalidationTrackers, so those objects continue tracking, then get cranky when their database is closed.
Attached is a sample project. Running the instrumentation tests should reproduce the problem.