当我第一次开始活动时,一切都很好,但是我可以正常导航,但是旋转屏幕后,fragmentMananger似乎出错了,每次更改片段后,如果旋转屏幕,活动就会加载一个空白片段重新创建出现了正确的片段,但错误仍然存在。
当我退出该应用程序并重新使用它时,错误仍然存在,并且仅在清除用户数据后才消失,我尝试在每次更改片段后重新创建活动,但这只会使事情变得更糟。
解决该问题的一件事是在每次应用程序完成后清除用户数据,但它会删除应用程序在运行时管理的重要数据,这些数据需要通过文件持久保存以便下次执行。
我使用一个伴随对象来管理片段名称:
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()
}
控件是一个具有一些功能和数据的对象,该功能和数据在整个App中通常使用
答案 0 :(得分:0)
在我的情况下,黑屏是由主线程阻塞引起的,在api更新后,一些不赞成使用的函数开始返回null并阻塞了片段中的主线程以解决问题,我使用了api提供的新函数替换不推荐使用的