how to fix crashing apps while using viewBinding, databinding , viewModel and fragment -  My app crash after installed on emulator ,



import android.annotation.SuppressLint
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.findNavController
import com.example.guessinggame.databinding.FragmentGameBinding

class GameFragment : Fragment() {
    private var _binding: FragmentGameBinding? = null
    private val binding get() = _binding!!
    private lateinit var viewModel: GameViewModel
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel = activity?.run {
            ViewModelProvider(this,)[GameViewModel::class.java]
        } ?: throw Exception("Invalid Activity")
    }

    @SuppressLint("SetTextI18n")
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View? {

        _binding = FragmentGameBinding.inflate(inflater, container, false)
       // _binding = DataBindingUtil.inflate(inflater, R.layout.fragment_game, container, false)
        val view = binding.root
       // viewModel = ViewModelProvider(this,)[GameViewModel::class.java]

        binding.gameViewModel = viewModel
        binding.lifecycleOwner = viewLifecycleOwner

        viewModel.gameOver.observe(viewLifecycleOwner, Observer { newValue ->
            if (newValue) {
                val action = GameFragmentDirections
                    .actionGameFragmentToResultFragment(viewModel.wonLostMessage())
                view.findNavController().navigate(action)
            }
        })

        binding.guessButton.setOnClickListener() {
            viewModel.makeGuess(binding.guess.text.toString().uppercase())
            binding.guess.text = null
        }
        return view
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }





This is xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".GameFragment">

    <data>

        <variable
            name="gameViewModel"
            type="com.example.guessinggame.GameViewModel" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        android:padding="20sp">

        <TextView
            android:id="@+id/word"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:letterSpacing="0.1"
            android:text="@{gameViewModel.secretWordDisplay}"
            android:textSize="36sp" />

        <TextView
            android:id="@+id/lives"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{@string/lives_left(gameViewModel.livesLeft)}"
            android:textSize="16sp" />

        <TextView
            android:id="@+id/incorrect_guesses"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{@string/incorrect_guesses(gameViewModel.incorrectGuesses)}"
            android:textSize="16sp" />

        <EditText
            android:id="@+id/guess"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:hint="Guess a letter"
            android:inputType="text"
            android:maxLength="1"
            android:textSize="16sp" />

        <Button
            android:id="@+id/guess_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="Guess!" />

        <Button
            android:id="@+id/finish_game_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:onClick="@{() -> gameViewModel.finishGame()}"
            android:text="Finish Game" />
    </LinearLayout>
</layout>


In build gradle

    buildFeatures {
        dataBinding = true
        //viewBinding = true
    }

string xml

<resources>
    <string name="app_name">GuessingGame</string>
    <!-- TODO: Remove or change this placeholder text -->
    <string name="hello_blank_fragment">Hello blank fragment</string>
    <string name="guess_a_letter">Guess a letter</string>
    <string name="guess_now">Guess Now</string>
    <string name="start_new_game">Start New Game</string>
    <string name="welcome_to_result">Welcome To Result</string>
    <string name="incorrect_guesses_s">Incorrect Guesses : %s</string>
    <string name="finish_game">Finish Game</string>
    <string name="lives_left">You have %d lives left</string>
    <string name="incorrect_guesses">Incorrect guesses: %s</string>
</resources>

I try many way to fix it . But still can't fix . Plz, help than in advance.

The error i got from logcat

FATAL EXCEPTION: main Process: com.example.guessinggame, PID: 9110 java.lang.RuntimeException: view must have a tag at com.example.guessinggame.DataBinderMapperImpl.getDataBinder(DataBinderMapperImpl.java:39) at androidx.databinding.MergedDataBinderMapper.getDataBinder(MergedDataBinderMapper.java:79) at androidx.databinding.DataBindingUtil.bind(DataBindingUtil.java:199) at androidx.databinding.DataBindingUtil.inflate(DataBindingUtil.java:130) at androidx.databinding.ViewDataBinding.inflateInternal(ViewDataBinding.java:1409) at com.example.guessinggame.databinding.FragmentGameBinding.inflate(FragmentGameBinding.java:78) at com.example.guessinggame.databinding.FragmentGameBinding.inflate(FragmentGameBinding.java:64) at com.example.guessinggame.GameFragment.onCreateView(GameFragment.kt:34) at androidx.fragment.app.Fragment.performCreateView(Fragment.java:3114) at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:557) at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:272) at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:114) at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1455) at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3034) at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:2945) at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3148) at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:588) at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:272) at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:114) at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1455) at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3034) at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2952) at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:263) at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:350) at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:251) at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1467) at android.app.Activity.performStart(Activity.java:8079) at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3710) at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221) at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201) at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2252) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7842) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003) 2023-08-04 13:53:42.803 9110-9121 System com.example.guessinggame W A resource failed to call close.

1

There are 1 best solutions below

1
On

Ur using both ViewBinding & DataBinding

  @SuppressLint("SetTextI18n")
override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
_binding = FragmentGameBinding.inflate(inflater, container, false)
   // _binding = DataBindingUtil.inflate(inflater, R.layout.fragment_game, container, false)
    val view = binding.root
   // viewModel = ViewModelProvider(this,)[GameViewModel::class.java]

From Above Code u enabled Viewbinding, commented DataBinding(disabled)

But in .xml file implemented DataBinding

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".GameFragment">

<data>

    <variable
        name="gameViewModel"
        type="com.example.guessinggame.GameViewModel" />
</data>

Remove This Part in .xml, means remove "</layout/>" tag, </data/> tags , bind the model object from GameFragment class Rebuild project & Run