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?
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;
}
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.
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.
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.
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();
}
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);
}
}
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();
}
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
}
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
}
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.
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.