0

I'm writing a celsius-farenheits converter but the program crashes for something that I didn't found

I'm actually trying to use the data binding and the view model but Android Studio founded some issues in ActivityMainBindingImpl.java that I didn't write by myself. Here's the part of code were it founds a problem. It is in line 104 at com.example.convertitorecelsius_farenheit.MainViewModel viewModel = mViewModel; It says "Cannot resolve symbol 'mViewModel'"

There's another problem in line 33 in "super(bindingComponent, root, 0", it says "'ActivityMainBinding()' has private access in 'com.example.convertitorecelsius_farenheit.databinding.ActivityMainBinding'"

The last problem is at line 8 in "public class ActivityMainBindingImpl extends ActivityMainBinding {", the error is in "ActivityMainBinding", it says "Cannot inherit from final 'com.example.convertitorecelsius_farenheit.databinding.ActivityMainBinding'"

Here's the full code where I founded these problems

package com.example.convertitorecelsius_farenheit.databinding;
import com.example.convertitorecelsius_farenheit.R;
import com.example.convertitorecelsius_farenheit.BR;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.view.View;
@SuppressWarnings("unchecked")
public class ActivityMainBindingImpl extends ActivityMainBinding  {

@Nullable
private static final androidx.databinding.ViewDataBinding.IncludedLayouts sIncludes;
@Nullable
private static final android.util.SparseIntArray sViewsWithIds;
static {
    sIncludes = null;
    sViewsWithIds = new android.util.SparseIntArray();
    sViewsWithIds.put(R.id.cambiaTemperatura, 3);
    sViewsWithIds.put(R.id.inputTemperatura, 4);
    sViewsWithIds.put(R.id.converti, 5);
}
// views
@NonNull
private final androidx.constraintlayout.widget.ConstraintLayout mboundView0;
// variables
// values
// listeners
// Inverse Binding Event Handlers

public ActivityMainBindingImpl(@Nullable androidx.databinding.DataBindingComponent bindingComponent, @NonNull View root) {
    this(bindingComponent, root, mapBindings(bindingComponent, root, 6, sIncludes, sViewsWithIds));
}
private ActivityMainBindingImpl(androidx.databinding.DataBindingComponent bindingComponent, View root, Object[] bindings) {
    super(bindingComponent, root, 0
        , (android.widget.Button) bindings[3]
        , (android.widget.Button) bindings[5]
        , (android.widget.EditText) bindings[4]
        , (android.widget.TextView) bindings[2]
        , (android.widget.TextView) bindings[1]
        );
    this.mboundView0 = (androidx.constraintlayout.widget.ConstraintLayout) bindings[0];
    this.mboundView0.setTag(null);
    this.textTemperatura.setTag(null);
    this.textView.setTag(null);
    setRootTag(root);
    // listeners
    invalidateAll();
}

@Override
public void invalidateAll() {
    synchronized(this) {
            mDirtyFlags = 0x2L;
    }
    requestRebind();
}

@Override
public boolean hasPendingBindings() {
    synchronized(this) {
        if (mDirtyFlags != 0) {
            return true;
        }
    }
    return false;
}

@Override
public boolean setVariable(int variableId, @Nullable Object variable)  {
    boolean variableSet = true;
    if (BR.viewModel == variableId) {
        setViewModel((com.example.convertitorecelsius_farenheit.MainViewModel) variable);
    }
    else {
        variableSet = false;
    }
        return variableSet;
}

public void setViewModel(@Nullable com.example.convertitorecelsius_farenheit.MainViewModel ViewModel) {
    this.mViewModel = ViewModel;
    synchronized(this) {
        mDirtyFlags |= 0x1L;
    }
    notifyPropertyChanged(BR.viewModel);
    super.requestRebind();
}

@Override
protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {
    switch (localFieldId) {
    }
    return false;
}

@Override
protected void executeBindings() {
    long dirtyFlags = 0;
    synchronized(this) {
        dirtyFlags = mDirtyFlags;
        mDirtyFlags = 0;
    }
    java.lang.String viewModelTypeCurrentTemperature = null;
    int viewModelConvertiTemperatura = 0;
    com.example.convertitorecelsius_farenheit.MainViewModel viewModel = mViewModel;

    if ((dirtyFlags & 0x3L) != 0) {



            if (viewModel != null) {
                // read viewModel.typeCurrentTemperature
                viewModelTypeCurrentTemperature = viewModel.getTypeCurrentTemperature();
                // read viewModel.convertiTemperatura()
                viewModelConvertiTemperatura = viewModel.convertiTemperatura();
            }
    }
    // batch finished
    if ((dirtyFlags & 0x3L) != 0) {
        // api target 1

        this.textTemperatura.setText(viewModelConvertiTemperatura);
        androidx.databinding.adapters.TextViewBindingAdapter.setText(this.textView, viewModelTypeCurrentTemperature);
    }
}
// Listener Stub Implementations
// callback impls
// dirty flag
private  long mDirtyFlags = 0xffffffffffffffffL;
/* flag mapping
    flag 0 (0x1L): viewModel
    flag 1 (0x2L): null
flag mapping end*/
//end

}

Here's the program I wrote MainActivity.java

package com.example.convertitorecelsius_farenheit;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;
import android.widget.EditText;

import com.example.convertitorecelsius_farenheit.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {

  private ActivityMainBinding binding;
  private MainViewModel viewModel;

  public EditText inputTemperature;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    inputTemperature = findViewById(R.id.inputTemperatura);

    binding = ActivityMainBinding.inflate(getLayoutInflater());
    binding.setLifecycleOwner(this);
    setContentView(binding.getRoot());

    viewModel = new ViewModelProvider(this).get(MainViewModel.class);
    binding.setViewModel(viewModel);
}

public int getInputTemperature() {
    return Integer.parseInt(inputTemperature.toString());
}}

MainViewModel.java

package com.example.convertitorecelsius_farenheit;

import androidx.lifecycle.ViewModel;

public class MainViewModel extends ViewModel {

public int grades;
public boolean isCelsius = false;

 MainActivity temperaturaInserita = new MainActivity();

 //private final MutableLiveData<String> _TypeCurrentTemperatura = new MutableLiveData<>();
 private String _TypeCurrentTemperatura = "";  //indicates if the temperature is celsius or farenheit

public String getTypeCurrentTemperature() {
    return _TypeCurrentTemperatura;
}

public void changeTypeTemperature() {
    if (isCelsius) {
        isCelsius = false;
        _TypeCurrentTemperatura = "F°";
    } else {
        isCelsius = true;
        _TypeCurrentTemperatura = "C°";
    }
}

public int convertiTemperatura() {  //convertTemperature (that's the italian name)
    if (isCelsius) {
        grades = (int) ((temperaturaInserita.getInputTemperature() * 1.8) + 32);
    } else {
        grades = (int) ((int) ((temperaturaInserita.getInputTemperature()) -32) * .5556);
    }
    return grades;
}}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

<data>
    <variable
        name="viewModel"
        type="com.example.convertitorecelsius_farenheit.MainViewModel" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="348dp"
        android:text="@{viewModel.typeCurrentTemperature}"
        android:textSize="24sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/cambiaTemperatura"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="80dp"
        android:text="c--f"
        app:layout_constraintBottom_toTopOf="@+id/textView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent" />

    <EditText
        android:id="@+id/inputTemperatura"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="52dp"
        android:ems="10"
        android:inputType="number"
        app:layout_constraintBottom_toTopOf="@+id/cambiaTemperatura"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/converti"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="273dp"
        android:layout_marginBottom="274dp"
        android:text="converti"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/inputTemperatura"
        app:layout_constraintVertical_bias="1.0" />

    <TextView
        android:id="@+id/textTemperatura"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="23dp"
        android:text="@{viewModel.convertiTemperatura()}"
        android:textSize="24sp"
        app:layout_constraintBottom_toTopOf="@+id/textView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Can somebody help me :)

1 Answers1

0

There are some things wrong in your code:

  • You're setting the activity view twice, remove the first line: setContentView(R.layout.activity_main);
  • Since you're using view binding (different thing from data binding), you dont need to call findViewById replace it with inputTemperature = binding.inputTemperatura
  • If you're already using data binding why bother with view binding? You can do all input/output related tasks in data binding.
  • You SHOULD NEVER instantiate ANDROID activities or hold a reference to it, this is task of the Android framework, remove the line MainActivity temperaturaInserita = new MainActivity(); of your viewmodel.

Check this answer it may help you: Android : Difference between DataBinding and ViewBinding

EDIT

You don't need to call methods of your activity from your viewmodel, this is a bad practice, because if the system destroys your activity you will end with a NPE in your view model, you have 2 options:

I recommend to go with first option, this way you will have the updated value always in your view model and also can survive config changes.

And remember don't matter what, your viewmodel SHOULD never have a reference to the Activity.

Nestor Perez
  • 827
  • 11
  • 17