why popbackstack removes the action/destination from the fragment? - kotlin

I'm building a notes application basically a clone of keep notes.
I want to save the note when the user press back button from the createNotesFragment and pop the fragment from the stack to move back to the homeFragment.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requireActivity()
.onBackPressedDispatcher
.addCallback(this) {
saveNote()
activity?.supportFragmentManager?.popBackStack()
}
}
the navigation from the homeFragmet works fine but after adding one note when I try to move back to the createNotesFragment. It shows me this error.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.lavanianotesapp, PID: 7351
java.lang.IllegalArgumentException: Navigation action/destination com.example.lavanianotesapp:id/action_homeFragment_to_createNotesFragment cannot be found from the current destination Destination(com.example.lavanianotesapp:id/createNotesFragment) label=fragment_create_notes class=com.example.lavanianotesapp.UI.Fragments.CreateNotesFragment
at androidx.navigation.NavController.navigate(NavController.kt:1540)
I don't understant before popBaCckStack it works fine but after I pop the fragment it doesn't works.
Thanks in advance.

Related

Navigating multi-module App with nested fragments

I'm trying to implement a multi-module app structure with navigation between modules. The challenge Im having is doing this with a structure that contains nested fragment containers.
Background:
The design uses a single activity.The main activity layout comprises of an actionbar and fragment container. This container is used to host the different 'main' module fragment.
<androidx.fragment.app.FragmentContainerView
android:id="#+id/frg_main_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph_app" />
Each module has a single 'parent' like fragment with a fragment container and bottomNavbar. This fragment container is used to host the detail fragments of each module and is the home fragment in the modules nav graph.
<androidx.fragment.app.FragmentContainerView
android:id="#+id/frg_home_contacts_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="false"
app:navGraph="#navigation/nav_graph_contacts" />
The app module contains a top level nav graph linking each modules parent fragment (these are not nested graphs or the modules nav graph, as the module's detail fragments are not used in the apps container view).
Each module has a bottom level nav graph linking the detail fragments of that module. This is used in conjunction with the bottomNavbar to navigate between module fragments [works].
For example, the goal is to have a button, on the home screen of the home module, that when clicked moves the user to a screen within another module, such as the contacts list screen in the Contact module.
There are two actions:
Navigate the Main container to the new module home fragment. (managed by the navContorller in the App)
Navigate the module container to the new details fragment. (managed by the navController in the module)
Presently I'm working with interfaces and trying to inject (hilt) into the main activity to achieve no.1. However, I'm always running into issues that the home module cant see the apps nav_graph or there are missing dependencies (i.e. it wants the dependency to get the nav_graph). I believe a simlar process should work between fragments for no.2
Concept reference: https://itnext.io/multi-module-navigation-in-android-63cb9924ffbd
This following code is functional when R.id.nav_graph_home but for links outside the module i.e. R.id.nav_graph_contacts it isnt.
interface HomeModuleNavInterface {
fun gotoContacts(navController: NavController)
}
class HomeModuleNavContract : HomeModuleNavInterface {
override fun gotoContacts(navController: NavController) {
navController.navigate(R.id.nav_graph_contacts)
}
}
#Module
#InstallIn(SingletonComponent::class)
class HomeNavigator {
#Singleton
#Provides
fun providesHomeNavInterface(): HomeModuleNavContract = HomeModuleNavContract()
}
class FragmentHomeNavigation : Fragment(R.layout.fragment_home_navigation) {
...
#Inject
lateinit var homeModuleNavigation: HomeModuleNavContract
...
btnContact.setOnCLickListener{
homeModuleNavigation.gotoContacts(findNavController())
}
}
Any suggestions or direction is appreciated. Thanks.

androidx.navigation:navigation-fragment:2.2.0, get "You must call removeView() on the child's parent first." on navController.popBackStack()

I like use data binding and navigation graph. But after update androidx dependencies from androidx.navigation:navigation-fragment:2.0.0 on 2.2.0 application is crashed after press button "Back". Crash always after return from other fragment to previous fragment containing FragmentPagerAdapter.
in build.gradle
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
// This is work
// implementation 'androidx.appcompat:appcompat:1.0.2'
// implementation 'androidx.navigation:navigation-fragment:2.0.0'
// This generate error after backstack
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.navigation:navigation-fragment:2.2.0'
}
For see a problem and getting error, please download example from https://github.com/ABRadzh/ErrorNavigation. Otherwise it will be difficult for me to explain where the error occurs.
Press on any button on any page.
Press hardware "Back" button.
Get error message:
2020-02-11 16:15:13.119 2429-2429/in.pagerview.navigation.databinding.onbackstack E/AndroidRuntime: FATAL EXCEPTION: main
Process: in.pagerview.navigation.databinding.onbackstack, PID: 2429
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:4954)
at android.view.ViewGroup.addView(ViewGroup.java:4785)
at androidx.viewpager.widget.ViewPager.addView(ViewPager.java:1485)
at android.view.ViewGroup.addView(ViewGroup.java:4725)
at android.view.ViewGroup.addView(ViewGroup.java:4698)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:326)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1497)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2625)
at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2577)
at androidx.fragment.app.Fragment.performActivityCreated(Fragment.java:2722)
at androidx.fragment.app.FragmentStateManager.activityCreated(FragmentStateManager.java:346)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1188)
at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2224)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1997)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1953)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6719)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:449)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
But all code for transition fragment and data binding is generated automatically. I do not known where i must call removeView().
If you try to use old dependencies, then invert all comments in code and layouts. And popBackStack() will work correctly.
I do not found anything about this error. May be, I do something incorrect?
The solution is just to add this code to every fragment:
#Override
public void onDestroyView() {
super.onDestroyView();
if(binding.getRoot().getParent() != null)
((ViewGroup)binding.getRoot().getParent()).removeView(binding.getRoot());
}
I really recommend you to create a BaseFragment which has this code and every fragment will extends from it, so you will not have to repeat the code on every fragment class.

Android DataBindingUtil.inflate causes InvocationTargetException

I'm working on an android application that registers consumptions of materials for production in warehouses. I am using Androids UI Navigation architecture component to handle the navigation within the app.
In every Fragment I am using the same onCreateView function:
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_layout, container, false)
return inflater.inflate(R.layout.fragment_layout, container, false)
}
where fragment_layout is the resource id of the current Fragments layout.
My problem now is, that in one single Fragment the call to DataBindingUtil.inflate is causing an InvocationTargetException.
I already commented out the complete layout to check if some errors are present in the layout file.
After that, I commented out all the logic for the views inside the fragment. This led to the same exception over and over again.
The last test I did was to change the line code inside onCreateView from
binding = DataBindingUtil.inflate(inflater, R.layout.consumption_fragment, container, false)
return binding.root
to:
return inflater.inflate(R.layout.fragment_layout, container, false)
After that, all the problems were gone.
But this solution is not suitable for me because I need to use the data bindings.
This is the data section of the layout file in question
<data>
<import type="Field" />
<import type="androidx.lifecycle.LiveData" />
<import type="java.util.List" />
<variable
name="parcelNo"
type="Field<String>" />
<variable
name="piece"
type="Field<String>" />
<variable
name="parcels"
type="LiveData<List<Consumption>>" />
<variable
name="parcel"
type="LiveData<Parcel>" />
</data>
The stack trace that is shown in the logcat does not provide very much information about where the error occurs.
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

Firebase Root View Controller Not Found Warning

I got a strange warning from Firebase Analytics today. It is:
<Warning> [Firebase/Analytics][I-ACS031011] Root view controller not found
The methods I am using is basically deleting a post and then displaying a status bar notification to the user that the post is deleted. This is the method that is called when we want to delete a post.
HomeViewNetwork.deletePost(postBlock: self.postDataBlock, handler: {
AlertManager.showStatusRed(title: "Post deleted!")
})
And my displaying status function is:
class func showStatusRed(title: String) {
let statusMessage = MessageView.viewFromNib(layout: .StatusLine)
var config = SwiftMessages.defaultConfig
config.presentationContext = .window(windowLevel: UIWindowLevelStatusBar)
statusMessage.configureContent(body: title)
statusMessage.backgroundView.backgroundColor = UIColor(red:0.98, green:0.11, blue:0.35, alpha:1.00)
setUpStatusView(messageView: statusMessage)
statusSwiftMessages.show(config: config, view: statusMessage)
}
The warning goes away if I comment the AlertManager.showStatusRed method. Also I am using SwiftMessages as my library for displaying the status bar notification.
I am not sure why Firebase is giving me this warning when Xcode is not giving any issues about root view controller. Any help is appreciated.
Related question for objective-C only project complied with Xcode 9 GM using FirebaseCore 4.0.4 (podfile.lock): Xcode 9 <Warning> [Firebase/Analytics][I-ACS031011] Root view controller not found
Updating the firebase and other related dependencies to latest version fixed the issue on my project.
- Firebase/Core (4.2.0):
- FirebaseAnalytics (= 4.0.3)
- FirebaseCore (= 4.0.7)
Answer on other thread: https://stackoverflow.com/a/46333312/342794

Adding PatternMatchListener to Eclipse Console in which stage of View Lifecycle

I am developing an Eclipse plug-in which will be triggered by a specific pattern string found (e.g., stack trace) in the default console opened in Eclipse and will show some notification in a custom view. I know how add the listener to the available consoles.But I am not sure in which phase of Eclipse View life cycle I need to add the listener. Currently I am adding in createPartControl which is not what I want, because it forces to me to open the view manually to perform the binding the listener with the consoles.
public void createPartControl(Composite parent) {
//got the default console from ConsolePlugin
TextConsole tconsole=(TextConsole)defaultConsole;
tconsole.addPatternMatchListener(new IPatternMatchListener() {
// implementation codes goes here
}
}
Any help will be appreciated.