我知道这个错误是很常见的,但我找不到一个解决我的问题的方式太多的地方这个错误是提出了。
我正在开发一个应用程序来存储和排序电视节目。我有一个主要的活动与一些片段,与一个HomeFragment
这是主页,与一个'添加节目'按钮,和下面的recyclerView
与我所有的节目。
当点击“添加节目”按钮时,我启动了一个新的活动,以填写一个表格,然后用提供的信息创建节目。这里没有问题,它应该工作。现在我试图通过在上面提到的recyclerView
中点击它们来添加编辑节目的可能性。这也带来了与“添加节目”按钮相同的活动,但这次是节目信息。
问题似乎就是从这个页面出现的。在表单Activity中,我有一个按钮,可以在其中为节目选择一个图像。编辑节目时,如果我更改图像,我不会收到错误,但如果我更改其他内容,例如名称,而不更改此图像,当单击确认按钮时,节目被正确编辑,但应用程序崩溃,并出现java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
错误。
错误似乎来自于片段部分,事务无法提交(我搜索了一段时间,所以我开始理解为什么它不工作,但不能确定是代码的哪一部分导致了这种情况)。
class HomeFragment(private val context: MainActivity) : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_home, container, false)
view.findViewById<Button>(R.id.button_add_show).setOnClickListener{
startActivity(Intent(context, AddShowActivity::class.java))
}
val verticalRecyclerView = view.findViewById<RecyclerView>(R.id.vertical_recycler_view)
verticalRecyclerView.adapter = ShowAdapter(context, showList, R.layout.item_show)
return view
}
}
这里是MainActivity
的加载部分:
private fun loadFragment(fragment: Fragment){
// Load repository
val repo = ShowRepository()
// Update shows list
repo.updateData{
// Inject fragment into fragment_container
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.fragment_container, fragment)
transaction.addToBackStack(null)
transaction.commit()
}
}
下面是我的AddShowActivity
的代码,它呈现要填充的表单:
class AddShowActivity : AppCompatActivity() {
private var fileImage: Uri? = null
private lateinit var uploadedImage: ImageView
private lateinit var editTextName: EditText
private lateinit var editTextNote: EditText
private lateinit var editTextDescription: EditText
private lateinit var editTextReview: EditText
private lateinit var datePicker: DatePicker
private var currentShow: ShowModel? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_add_show)
setupComponents()
setupButtons()
// Get show when editing
if(intent.extras != null){
val position = intent.extras!!.getInt("position")
currentShow = showList[position]
}
initializeComponents()
}
private fun setupComponents() {
editTextName = findViewById(R.id.name_input)
editTextNote = findViewById(R.id.note_input)
editTextDescription = findViewById(R.id.description_input)
editTextReview = findViewById(R.id.review_input)
uploadedImage = findViewById(R.id.preview_image)
datePicker = findViewById(R.id.watch_date_input)
}
private fun setupButtons(){
val pickupImageButton = findViewById<Button>(R.id.upload_image_button)
pickupImageButton.setOnClickListener{
pickupImage()
}
val confirmButton = findViewById<Button>(R.id.confirm_button)
confirmButton.setOnClickListener{
sendForm()
val toastText = when(currentShow){
null -> "Show added"
else -> "Show edited"
}
Toast.makeText(this, toastText, Toast.LENGTH_SHORT).show()
this.finish()
}
}
@SuppressLint("NewApi")
private fun initializeComponents() {
if(currentShow != null){
editTextName.setText(currentShow!!.name)
editTextNote.setText(currentShow!!.note.toString())
editTextDescription.setText(currentShow!!.description)
editTextReview.setText(currentShow!!.review)
Glide.with(this).load(Uri.parse(currentShow!!.imageUrl)).into(uploadedImage)
}
}
private fun sendForm(){
val repo = ShowRepository()
if(fileImage == null)createShow(repo)
else{
if(currentShow != null)repo.deleteImage(currentShow!!)
repo.uploadImage(fileImage!!){
createShow(repo)
}
}
}
private fun createShow(repo: ShowRepository){
val showName = editTextName.text.toString()
val showNote = parseInt(editTextNote.text.toString())
val description = editTextDescription.text.toString()
val review = editTextReview.text.toString()
val showWatchDate = getWatchDate(datePicker)
val downloadImageUrl = downloadImageUri.toString()
val show = ShowModel(UUID.randomUUID().toString(), showName, showWatchDate, showNote, downloadImageUrl, description, review)
if(currentShow != null){
show.id = currentShow!!.id
repo.updateShow(show)
}
else repo.insertShow(show)
}
private fun getWatchDate(datePicker: DatePicker): String {
var day = datePicker.dayOfMonth.toString()
if(day.toInt() < 10)day = "0$day"
var month = (datePicker.month + 1).toString()
if(month.toInt() < 10)month = "0$month"
val year = datePicker.year.toString()
return "$day-$month-$year"
}
private fun pickupImage(){
val intent = Intent()
intent.type = "image/"
intent.action = Intent.ACTION_GET_CONTENT
startActivityForResult(Intent.createChooser(intent, "Select Picture"), 47)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(resultCode == Activity.RESULT_OK && requestCode == 47){
if(data == null || data.data == null)return
fileImage = data.data
uploadedImage.setImageURI(fileImage)
}
}
}
这里是ShowRepository
,它处理与Firebase数据库的通信:
class ShowRepository {
object Singleton{
// Link to bucket
private val BUCKET_URL: String = "gs://tv-memories.appspot.com"
// Storage connexion
val storageReference = FirebaseStorage.getInstance().getReferenceFromUrl(BUCKET_URL)
// Database connexion
val databaseRef = FirebaseDatabase.getInstance().getReference("shows")
// List containing all shows
val showList = arrayListOf<ShowModel>()
// Contains current image link
var downloadImageUri: Uri? = null
}
fun updateData(callback: () -> Unit){
// Absorb data from databaseRef
databaseRef.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
// Remove old shows
showList.clear()
// Get list
for(ds in snapshot.children){
//Build show object
val show = ds.getValue(ShowModel::class.java)
// Verify show isn't null
if(show != null){
// Add show to the list
showList.add(show)
}
}
// Activate callback
callback()
}
override fun onCancelled(p0: DatabaseError) {
}
})
}
// Upload files on storage
fun uploadImage(file: Uri, callback: () -> Unit){
val fileName = UUID.randomUUID().toString() + ".jpg"
val ref = storageReference.child(fileName)
val uploadTask = ref.putFile(file)
uploadTask.continueWithTask(Continuation<UploadTask.TaskSnapshot, Task<Uri>>{ task ->
if(!task.isSuccessful){
task.exception?.let{throw it}
}
return@Continuation ref.downloadUrl
}).addOnCompleteListener{ task ->
if(task.isSuccessful){
downloadImageUri = task.result
callback()
}
}
}
fun deleteImage(show: ShowModel){
val photoRef: StorageReference = FirebaseStorage.getInstance().getReferenceFromUrl(show.imageUrl)
photoRef.delete()
}
fun updateShow(show: ShowModel) = databaseRef.child(show.id).setValue(show)
fun insertShow(show: ShowModel) = databaseRef.child(show.id).setValue(show)
fun deleteShow(show: ShowModel){
databaseRef.child(show.id).removeValue()
deleteImage(show)
}
}
以及错误的完整追溯:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: fr.steph.showmemories, PID: 18296
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at androidx.fragment.app.FragmentManager.checkStateLoss(FragmentManager.java:1844)
at androidx.fragment.app.FragmentManager.enqueueAction(FragmentManager.java:1884)
at androidx.fragment.app.BackStackRecord.commitInternal(BackStackRecord.java:329)
at androidx.fragment.app.BackStackRecord.commit(BackStackRecord.java:294)
at fr.steph.showmemories.MainActivity$loadFragment$1.invoke(MainActivity.kt:49)
at fr.steph.showmemories.MainActivity$loadFragment$1.invoke(MainActivity.kt:44)
at fr.steph.showmemories.ShowRepository$updateData$1.onDataChange(ShowRepository.kt:61)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(ValueEventRegistration.java:75)
at com.google.firebase.database.core.view.DataEvent.fire(DataEvent.java:63)
at com.google.firebase.database.core.view.EventRaiser$1.run(EventRaiser.java:55)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7078)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)
1条答案
按热度按时间mzaanser1#
我终于找到了解决问题的方法,即在我的
loadFragment()
方法中用transaction.commitAllowingStateLoss()
替换transaction.commit()
,以防状态已经保存。然后我得到