Android DataBindingUtil.inflate causes InvocationTargetException - kotlin

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)

Related

why popbackstack removes the action/destination from the fragment?

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.

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.

NavigationError on NavigateTo

I'm trying out Blazor ServerSide and created a Component to Redirect To the Login Page when a user is not logged in.
#inject Microsoft.AspNetCore.Components.NavigationManager NavigationManager;
#code {
/// <inheritdoc />
protected override Task OnInitializedAsync()
{
NavigationManager.NavigateTo("Login");
return Task.CompletedTask;
}
}
But always when "NavigateTo" is called the following exception is thrown:
"Microsoft.AspNetCore.Components.NavigationException: Exception of type 'Microsoft.AspNetCore.Components.NavigationException' was thrown.
at Microsoft.AspNetCore.Components.Server.Circuits.RemoteNavigationManager.NavigateToCore(String uri, Boolean forceLoad)
at Microsoft.AspNetCore.Components.NavigationManager.NavigateTo(String uri, Boolean forceLoad)
at ApplySupportTool.Blazor.Pages.RedirectToLogin.OnInitializedAsync() in C:\\Users\\padruttn\\Documents\\git\\ApplySupportTool\\src\\ApplySupportTool.Blazor\\Pages\\RedirectToLogin.razor:line 8"
Interesstingly the navigation is made despite the exception.
I also tried to call it with the path "/login" but the same behaviour here.
There is an open issue on github for this problem. See also the preceeding issue where a possible workaround is mentioned: putting the NavigateTo method into OnAfterRender instead of OnInitialized.
I needed to put this into OnInitialized rather than OnAfterRender, so had to go with the render-mode="Server" method, though apparently this isn't recommended.
It also states in the GitHub issue that this only happens in debug, not release, so a middle ground option is to change _Host.cshtml to contain:
<environment include="Staging,Production">
<component render-mode="ServerPrerendered" type="typeof(App)" />
</environment>
<environment include="Development">
<component render-mode="Server" type="typeof(App)" />
</environment>
Note that the following may be considered a workaround:
You may also change your method to the following including the "async" keyword to its signature, there is going to be a complaint about not using await, but in exchange you are not going to need a return value. Since it doesn't have an 'await' the effect is kinda the same as the synchronous version, but without the exception being thrown.
protected override async Task OnInitializedAsync()
{
NavigationManager.NavigateTo("Login");
}
Here is an example where i am using a RedirectToLogin.razor component in my routing
#inject NavigationManager NavigationManager
#code{
protected override async Task OnInitializedAsync()
{
var returnUrl = "~/" + NavigationManager.ToBaseRelativePath(NavigationManager.Uri);
NavigationManager.NavigateTo($"Identity/Account/Login?returnUrl={returnUrl}", forceLoad:false);
}
}
And in my App.razor
<Found Context="routeData">
<AuthorizeRouteView RouteData="#routeData" DefaultLayout="#typeof(MainLayout)">
<NotAuthorized>
<RedirectToLogin />
</NotAuthorized>
</AuthorizeRouteView>
</Found>
Old post, but - if you are running a Blazor Server app, this behavior only happens if render-mode is "ServerPrerendered". Disabling Pre-rendering by changing the mode to "Server" makes the exception not be thrown in the first place:
<app>
<component type="typeof(App)" render-mode="Server" />
</app>
I've searched current Blazor Documentation and change notes, and haven't found any mention of this, so just in case it helps somebody else...
I ran into the same problem and filed issue #28355. The official answer is, that it is save to ignore the exception when NaviagteTo is placed in OnInitialized. Here is the answer from javiercn:
Yes, it is completely safe to ignore it. The debugger stops because it is configured to do so, but in this case the exception is always handled. You can turn-off breaking on this exception if it's caught on the debugger settings.
Issue #13582 deals with how to prevent the debugger from stopping at this exception.
use OnInitializedAsync replace OnInitialized
protected override async Task OnInitializedAsync()
{
nav.NavigateTo("/login", true);
await base.OnInitializedAsync();
}
I had this when I tried to call the navigateto from another thread. render-mode = "Server" - solved the problem
In .NET 5.0, in the _host.cshtml file. Past the following #(await Html.RenderComponentAsync(RenderMode.Server)) in the line after the "blazor_error_ui" section.

In react native how do I change root view background color on Android?

I have read a couple of tutorials online but most of the talk of iOS or some talk of Android but using old versions of react, everything has changed now.
If I open MainActivity.java there's only one method
#Override
protected String getMainComponentName() {
return "myapp";
}
which means I can't access the rootview and change its background color because it seems even the onCreate method isn't available to anyone nowadays.
I also tried opening res/styles and adding my lines there but I keep getting errors
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">#android:color/black</item>
</style>
I tried that but nothing changes, still the same grayish background appears.
Wish I could just do it in react but adding background there not only adds unnecessary overdraws, when loading there's this lag with one background then later changes to another, its very ugly.
In android/app/src/main/res/values/:
Create (or edit) colors.xml to add your background color, e.g.:
<resources>
<color name="background">#AB47BC</color>
</resources>
In styles.xml, add a theme customization item named android:windowBackground, referencing the chosen color name, e.g.:
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">#color/background</item>
</style>
</resources>
I created a library, it allows you to do it from the level of JavaScript, and also allows you to do dynamic changes.
https://github.com/johniak/react-native-root-view-background
import { setRootViewBackgroundColor } from 'react-native-root-view-background';
export default class Main extends Component {
componentDidMount(){
setRootViewBackgroundColor('#ccc');
}
}
The downside of this solution is that color is set after JS is loaded.
You need to implement React styling to change the background color.