wake-up-neo.com

Verwendung der Datenbindung mit Fragment

Ich versuche, dem Datenbindungsbeispiel aus dem offiziellen Google Doc https://developer.Android.com/tools/data-binding/guide.html zu folgen.

außer dass ich versuche, Daten auf ein Fragment anzuwenden, nicht auf eine Aktivität.

der fehler den ich gerade beim kompilieren bekomme ist

Error:(37, 27) No resource type specified (at 'text' with value '@{marsdata.martianSols}.

onCreate für fragment sieht so aus:

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    MartianDataBinding binding = MartianDataBinding.inflate(getActivity().getLayoutInflater());
    binding.setMarsdata(this);
}

onCreateView für fragment sieht so aus:

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    return inflater.inflate(R.layout.martian_data, container, false);
}

und Teile meiner Layoutdatei für Fragmente sehen folgendermaßen aus:

<?xml version="1.0" encoding="utf-8"?>

<layout xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <data>
        <variable
            name="marsdata"
            type="uk.co.darkruby.app.myapp.MarsDataProvider" />
    </data>
...

        <TextView
            Android:layout_height="wrap_content"
            Android:layout_width="wrap_content"
            Android:text="@{marsdata.martianSols}"
        />

    </RelativeLayout>
</layout>

mein Verdacht ist, dass MartianDataBinding nicht weiß, mit welcher Layoutdatei es verbunden werden soll - daher der Fehler. Irgendwelche Vorschläge?

114
dark_ruby

Die Datenbindungsimplementierung muss sich in der onCreateView-Methode des Fragments befinden. Löschen Sie alle Datenbindungen, die in Ihrer OnCreate-Methode vorhanden sind.

public View onCreateView(LayoutInflater inflater, 
                         @Nullable ViewGroup container, 
                         @Nullable Bundle savedInstanceState) {
    MartianDataBinding binding = DataBindingUtil.inflate(
            inflater, R.layout.martian_data, container, false);
    View view = binding.getRoot();
    //here data must be an instance of the class MarsDataProvider
    binding.setMarsdata(data);
    return view;
}
245

Es wird tatsächlich empfohlen, die inflate-Methode Ihrer generierten Bindung zu verwenden und nicht die DataBindingUtil:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    MainFragmentBinding binding = MainFragmentBinding.inflate(inflater, container, false);
    //set variables in Binding
    return binding.getRoot();
}

Dokumente für DataBindingUtil.inflate () :

Verwenden Sie diese Version nur, wenn layoutId vorher nicht bekannt ist. Verwenden Sie andernfalls die aufgeblasene Aufblasmethode von Binding, um eine typsichere Inflation zu gewährleisten.

38
Till

Versuchen Sie dies in Android DataBinding

FragmentMainBinding binding;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_main, container, false);
        View rootView = binding.getRoot();
        initInstances(savedInstanceState);
        return rootView;
}

Man kann einfach Ansichtsobjekte wie unten erwähnt abrufen

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

View view = DataBindingUtil.inflate(inflater, R.layout.layout_file, container, false).getRoot();

return view;

}

Sogar die anderen Antworten funktionieren vielleicht gut, aber ich möchte den besten Ansatz sagen.

Verwenden Sie Binding class's inflate wie in Android-Dokumentation empfohlen empfohlen.

Eine Option ist das Aufblasen um DataBindingUtil, aber wenn nur Sie nicht wissen, haben sie die Bindungsklasse generiert.

- Sie haben automatisch binding class generiert, verwenden Sie diese Klasse anstelle von DataBindingUtil.

In Java 

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    HomeFragmentBinding binding = HomeFragmentBinding.inflate(inflater, container, false);
    //set binding variables here
    return binding.getRoot();
}

In Kotlin

lateinit var binding: HomeFragmentBinding 
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    binding = HomeFragmentBinding.inflate(inflater, container, false)
    return binding.root
}

In DataBindingUtil Klasse Dokumentation können Sie sehen.

aufblasen

T inflate (LayoutInflater inflater, 
                int layoutId, 
                ViewGroup parent, 
                boolean attachToParent)

Verwenden Sie diese Version nur, wenn layoutId vorher nicht bekannt ist. Verwenden Sie andernfalls die aufgeblasene Methode der generierten Bindung, um typsichere Inflation.

Wenn Ihre Layout-Biniding-Klasse nicht generiert wird, @See diese Antwort.

6
Khemraj

in meinem Code arbeiten.

private FragmentSampleBinding dataBiding;
private SampleListAdapter mAdapter;

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);
    dataBiding = DataBindingUtil.inflate(inflater, R.layout.fragment_sample, null, false);
    return mView = dataBiding.getRoot();
}
5
UJWAL GHONGADE

Ein vollständiges Beispiel für die Datenbindung von Fragmenten

FragmentMyProgramsBinding ist eine Bindungsklasse, die für res/layout/fragment_my_programs generiert wird

public class MyPrograms extends Fragment {
    FragmentMyProgramsBinding fragmentMyProgramsBinding;

    public MyPrograms() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
    FragmentMyProgramsBinding    fragmentMyProgramsBinding = DataBindingUtil.inflate(inflater, R
                .layout.fragment_my_programs, container, false);
        return fragmentMyProgramsBinding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

    }
}
4
vivek yadav

Genau wie die meisten gesagt haben, aber vergessen Sie nicht, LifeCycleOwner einzustellen
Beispiel in Java d

public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);
    BindingClass binding = DataBindingUtil.inflate(inflater, R.layout.fragment_layout, container, false);
    ModelClass model = ViewModelProviders.of(getActivity()).get(ViewModelClass.class);
    binding.setLifecycleOwner(getActivity());
    binding.setViewmodelclass(model);

    //Your codes here

    return binding.getRoot();
}
3
Lefty

Kotlin-Syntax:

lateinit var binding: MartianDataBinding
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    binding = DataBindingUtil.inflate(inflater, R.layout.martian_data, container, false)
    return binding.root
}
2
muneikh

Wenn Sie ViewModel und LiveData verwenden, ist dies die ausreichende Syntax

Kotlin-Syntax:

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    return MartianDataBinding.inflate(
        inflater,
        container,
        false
    ).apply {
        setLifecycleOwner([email protected])
        vm = viewModel    // Attach your view model here
    }.root
}
0
Saman Sattari

Ein anderes Beispiel in Kotlin:

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val binding = DataBindingUtil
            .inflate< MartianDataBinding >(
                    inflater,
                    R.layout.bla,
                    container,
                    false
            )

    binding.modelName = // ..

    return binding.root
}

Beachten Sie, dass der Name "MartianDataBinding" vom Namen der Layoutdatei abhängt. Wenn die Datei "martian_data" heißt, lautet der korrekte Name MartianDataBinding.

0
akohout

Jeder sagt über inflate(), aber was ist, wenn wir es in onViewCreated() verwenden wollen?

Sie können die Methodebind(view)der konkreten Bindungsklasse verwenden, um die Instanz ViewDataBinding für die view abzurufen.


Normalerweise schreiben wir BaseFragment so (vereinfacht):

// BaseFragment.kt
abstract fun layoutId(): Int

override fun onCreateView(inflater, container, savedInstanceState) = 
    inflater.inflate(layoutId(), container, false)

Und verwenden Sie es in Kindfragment.

// ConcreteFragment.kt
override fun layoutId() = R.layout.fragment_concrete

override fun onViewCreated(view, savedInstanceState) {
    val binding = FragmentConcreteBinding.bind(view)
    // or
    val binding = DataBindingUtil.bind<FragmentConcreteBinding>(view)
}


Wenn für alle Fragmente die Datenbindung verwendet wird, können Sie sie mithilfe von Typparametern sogar vereinfachen.

abstract class BaseFragment<B: ViewDataBinding> : Fragment() {
    abstract fun onViewCreated(binding: B, savedInstanceState: Bundle?)

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        onViewCreated(DataBindingUtil.bind<B>(view)!!, savedInstanceState)
    }
}

Ich weiß nicht, ob es in Ordnung ist, dort einen Wert ungleich Null zu behaupten, aber ... Sie haben die Idee. Wenn Sie möchten, dass es nullfähig ist, können Sie es tun.

0
Tura