Фрагмент изменяется на бланковый фрагмент после уничтожения - PullRequest
0 голосов
/ 13 ноября 2018

Когда я начинаю свою деятельность в первый раз, все в порядке, я могу нормально перемещаться, но после поворота экрана фрагмент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()
}

Элемент управления - это объект с некоторыми функциями и данными, которые обычно используются в приложении

1 Ответ

0 голосов
/ 19 января 2019

в моем случае пустой экран был вызван заблокированным основным потоком, после обновления API некоторые устаревшие функции начали возвращать ноль и блокировать основной поток внутри фрагментов для решения проблемы. Я использовал новые функции, предоставленные API длязаменить устаревшие

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...