Когда я начинаю свою деятельность в первый раз, все в порядке, я могу нормально перемещаться, но после поворота экрана фрагментMananger, как представляется, выдает ошибку, и после каждого изменения фрагмента он загружает пустой фрагмент, если я поворачиваю экран, и активность воссоздан правильный фрагмент появляется, но ошибка сохраняется.
Когда я закрываю приложение и возвращаюсь к нему, ошибка сохраняется и исчезает только после очистки пользовательских данных, я пытаюсь воссоздать действие после каждого изменения фрагмента, но оно только ухудшает ситуацию.
Единственное, что решает проблему, - это очищать пользовательские данные после каждой доработки приложения, но при этом стираются важные данные, управляемые приложением во время выполнения, которые необходимо сохранить через файл для следующего выполнения.
Я использую объект-компаньон для управления именами фрагментов:
companion object {
val TAG = this::class.java.canonicalName!!
const val MAIN_FRAGMENT = "MainFragment"
const val SECOND_FRAGMENT = "SecondFragment"
const val THIRD_FRAGMENT = "ThirdFragment"
const val FOURTH_FRAGMENT = "FourthFragment"
const val FIFTH_FRAGMENT = "FifthFragment"
}
функции для управления фрагментами:
fun callFragment(s: String? = null) {
validateFrag(s ?: MAIN_FRAGMENT, ::setFragment)
}
fun updateFragment() {
Control.logData("updating fragment $fragment_state")
validateFrag(fragment_state, ::setFragment)
}
private fun validateFrag(s: String, f: (String) -> Unit) {
when (s) {
SECOND_FRAGMENT -> f(s)
THIRD_FRAGMENT -> f(s)
FOURTH_FRAGMENT -> f(s)
FIFTH_FRAGMENT -> f(s)
else -> f(MAIN_FRAGMENT)
}
}
private fun createFrag(id: String): Fragment = when (id) {
SECOND_FRAGMENT -> SecondFragment.newInstance()
THIRD_FRAGMENT -> ThirdFragment.newInstance()
FOURTH_FRAGMENT -> FourthFragment.newInstance()
FIFTH_FRAGMENT -> FifthFragment.newInstance(this)
else -> MainFragment.newInstance()
}
private fun setFragment(id: String) {
val userAuth = userAuth
userAuth ?: return
Control.logData("loading fragment $id")
val frame = R.id.app_frame
val fragment = (fragmentManager.findFragmentByTag(id) ?: createFrag(id))
currentFragment = fragment as MyAppFragment
fragment_state = id
when{
fragmentManager.fragments.size == 0 -> {
fragmentManager.beginTransaction()
.add(frame, createFrag(MAIN_FRAGMENT), MAIN_FRAGMENT)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commitNowAllowingStateLoss()
}
!fragmentManager.fragments.contains(fragment as Fragment) -> {
fragmentManager.beginTransaction()
.add(frame, fragment, id)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commitNowAllowingStateLoss()
}
else ->{
with(fragmentManager.beginTransaction()) {
replace(frame, fragment, id)
setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
commitNowAllowingStateLoss()
}
}
}
}
для коммитов, которые я пытаюсь выполнить Commit (), CommitNow () тоже
мой фрагмент реализации:
package com.domain.app.fragments
import android.content.Context
import android.support.v4.app.Fragment
import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.ScrollView
import com.reactivex.disposables.Disposable
import com.domain.app.Control
import com.domain.app.R
import com.domain.app.AppApplicatcomn
import com.domain.app.activities.appActivity
import com.domain.app.dagger.services.IRXService
import com.domain.app.recycler.adapter.DataListAdapter
import kotlinx.android.synthetic.main.fragment_main.*
import javax.inject.Inject
class MainFragment : Fragment(), AppFragment {
// instanciate data
compancomn object {
fun newInstance(): MainFragment{
return MainFragment()
}
}
override fun onAttach(context: Context?) {
super.onAttach(context)
activity?.let { act ->
//subscribe RX
}
}
override fun onDetach() {
super.onDetach()
//disposeRX
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_main, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
dockInit()
recyclerInit()
if(Control.index.isEmpty()){
noDataScreen()
}
else{
Control.putOnScreen()
}
}
override fun noDataScreen() {
activity?.runOnUiThread {
main_noDataQrButton?.visibility = View.VISIBLE
main_noDataText?.visibility = View.VISIBLE
Control.loadingDataStream.onNext(false)
isInit = false
}
}
override fun notifyRecycler() {
activity?.runOnUiThread{
if(::list.isInitialized){
mAdapter.update()
list.adapter?.notifyDataSetChanged()
}
}
}
private fun recyclerInit(){
mAdapter = DataListAdapter(activity as appActivity)
mAdapter.setHasStableIds(true)
list = view!!.findViewById<RecyclerView>(R.id.main_listDataListRecycler).apply {
setHasFixedSize(true)
setItemViewCacheSize(8)
layoutManager = LinearLayoutManager(context)
adapter = mAdapter
}
}
}
мой манифест:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.domain.app">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:name=".AppApplication"
android:allowBackup="true"
android:icon="@drawable/app"
android:label="@string/app_name"
android:roundIcon="@drawable/app_round"
android:supportsRtl="true"
android:theme="@style/AppTheme.NoActionBar"
android:allowClearUserData="true"
android:fullBackupContent="@xml/backup_descriptor">
<!-- android:theme="@style/AppTheme" -->
<activity
android:name=".activities.AppActivity"
android:screenOrientation="portrait"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<!-- para ser aberto com action APP -->
<action android:name="android.intent.action.APP" />
<action android:name="android.intent.action.MAIN" />
<action android:name="io.ubivis.digitalmobility.action.CONSUME_APP_NOTIFICATION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="app.domain.io"
android:scheme="https" />
</intent-filter>
</activity>
<service android:name=".services.FirebaseMessageService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name=".services.FirebaseTokenService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/ic_logo_app_60dp" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/colorPrimary" />
<!-- Para Android 8 - Necessário um canal para notificações -->
<!-- <meta-data -->
<!-- android:name="com.google.firebase.messaging.default_notification_channel_id" -->
<!-- android:value="@string/default_notification_channel_id"/> -->
</application>
xml моей активности:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.CardView
android:id="@+id/app_connectionCard"
android:layout_width="match_parent"
android:layout_height="40dp"
android:visibility="gone"
app:cardBackgroundColor="@android:color/holo_red_dark"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/app_toolbar">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/connectionFail"
android:textColor="@color/cardview_light_background"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.Toolbar
android:id="@+id/app_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/ubivis_background_blue"
android:theme="@style/ThemeOverlay.AppCompat.Dark"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.v4.widget.DrawerLayout
android:id="@+id/app_drawer"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/app_connectionCard"
tools:openDrawer="start">
<FrameLayout
android:id="@+id/app_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</FrameLayout>
<android.support.design.widget.NavigationView
android:id="@+id/app_navigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="@color/colorPrimaryDark"
android:fitsSystemWindows="true"
android:theme="@style/UbivisDrawerTheme"
app:headerLayout="@layout/nav_header_app"
app:itemIconTint="@color/ubivis_orange"
app:menu="@menu/activity_app_drawer" />
</android.support.v4.widget.DrawerLayout>
фрагмент xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:theme="@style/AppTheme.NoActionBar"
tools:context=".fragments.MainFragment">
<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:adjustViewBounds="false"
android:cropToPadding="false"
android:scaleType="fitEnd"
android:tint="@color/background"
android:translationX="128dp"
android:translationY="128dp"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/logo_domain_vasado" />
<android.support.v7.widget.RecyclerView
android:id="@+id/main_listDataListRecycler"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/main_dock"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0">
</android.support.v7.widget.RecyclerView>
<TextView
android:id="@+id/main_noDataText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:text="@string/noDataMessage"
android:textAlignment="center"
android:textSize="30sp"
android:textStyle="bold"
android:visibility="visible"
app:layout_constraintBottom_toTopOf="@+id/main_noDataQrButton"
app:layout_constraintEnd_toStartOf="@+id/main_dock"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/main_noDataQrButton"
android:layout_width="220dp"
android:layout_height="220dp"
android:layout_marginBottom="5dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="30dp"
android:background="@drawable/shape_qr_code_frame"
android:elevation="16dp"
android:onClick="qrScan"
android:theme="@style/AppTheme"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/main_dock"
app:layout_constraintStart_toStartOf="@+id/main_listDataListRecycler"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="OnClick" />
для жизненного цикла действия:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Control.logData("creating activity")
setContentView(R.layout.activity_app)
// keep screen alive
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
// set toolbar
setSupportActionBar(findViewById(R.id.app_toolbar))
supportActionBar?.title = getString(R.string.Datas)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
isWaitingResult = savedInstanceState?.getBoolean(isWaitingResultCode) ?: false
savedInstanceState?.let{
fragment_state = savedInstanceState.getString(fragState) ?: fragment_state
userAuth = savedInstanceState.getSerializable(userAuthCode) as? UserAuthentication?
}
val DataMenu = findViewById<NavigationView>(R.id.app_navigation)
.menu.findItem(R.id.DataButton)
DataMenu?.isChecked = true
if (!Control.filters) filterMenu?.icon = drawable(R.drawable.filter_inactive)
//injection
if (!isInjected) {
onInject()
}
}
override fun onStop() {
super.onStop()
Control.logData("stopping activity")
fragmentManager.executePendingTransactions()
Control.mainRunning = false
loop = false
saveFav()
}
override fun onDestroy() {
super.onDestroy()
Control.logData("destroying activity")
Control.rx.forEach { it.dismiss() }
Control.rx.clear()
}
Элемент управления - это объект с некоторыми функциями и данными, которые обычно используются в приложении