J'essaie de suivre un exemple de liaison de données tiré de Google Doc officiel https://developer.Android.com/tools/data-binding/guide.html
sauf que j'essaie d'appliquer une liaison de données à un fragment, pas à une activité.
l'erreur que je reçois actuellement lors de la compilation est
Error:(37, 27) No resource type specified (at 'text' with value '@{marsdata.martianSols}.
onCreate
pour fragment ressemble à ceci:
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MartianDataBinding binding = MartianDataBinding.inflate(getActivity().getLayoutInflater());
binding.setMarsdata(this);
}
onCreateView
pour fragment ressemble à ceci:
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.martian_data, container, false);
}
et des parties de mon fichier de mise en page pour fragment ressemblent à ceci:
<?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>
je soupçonne que MartianDataBinding
ne sait pas à quel fichier de mise en page il est supposé être lié - d'où l'erreur. Aucune suggestion?
L'implémentation de la liaison de données doit figurer dans la méthode onCreateView du fragment. Supprimez toutes les liaisons de données existant dans votre méthode OnCreate, Votre onCreateView devrait ressembler à ceci:
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;
}
Vous êtes réellement encouragé à utiliser la méthode inflate
de votre liaison générée et non la méthode 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();
}
Docs for DataBindingUtil.inflate () :
Utilisez cette version uniquement si layoutId est inconnu à l’avance. Sinon, utilisez la méthode de gonflage de Binding générée pour garantir un gonflage conforme au type.
Essayez ceci dans 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;
}
On peut simplement récupérer un objet de vue comme mentionné ci-dessous
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;
}
Même les autres réponses peuvent bien fonctionner, mais je veux dire la meilleure approche.
Binding class's inflate
comme recommandé dans Documentation Android.Une option consiste à gonfler de DataBindingUtil
mais seulement si vous ne le savez pas, avez généré la classe de liaison.
--Vous avez généré automatiquement binding class
, utilisez cette classe au lieu de DataBindingUtil
.
En 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();
}
À Kotlin
lateinit var binding: HomeFragmentBinding
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = HomeFragmentBinding.inflate(inflater, container, false)
return binding.root
}
Dans DataBindingUtil, vous pouvez voir la classe documentation.
gonfler
T inflate (LayoutInflater inflater, int layoutId, ViewGroup parent, boolean attachToParent)
Utilisez cette version uniquement si layoutId est inconnu à l'avance. Sinon, utilisez la méthode de gonflage de Binding générée pour garantir la sécurité du type inflation.
Si votre classe de mise en page n'est pas générée @Voir cette réponse.
travailler dans mon code.
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();
}
Un exemple complet dans les fragments de liaison de données
FragmentMyProgramsBinding est une classe de liaison générée pour res/layout/fragment_my_programs
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);
}
}
Tout comme la plupart l'ont dit, mais n'oubliez pas de définir LifeCycleOwner
échantillon en Java i.e
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();
}
Syntaxe Kotlin:
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
}
Si vous utilisez ViewModel et LiveData Ceci est la syntaxe suffisante
Syntaxe de Kotlin:
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return MartianDataBinding.inflate(
inflater,
container,
false
).apply {
setLifecycleOwner(this@MartianData)
vm = viewModel // Attach your view model here
}.root
}
Un autre exemple à 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
}
Notez que le nom "MartianDataBinding" dépend du nom du fichier de mise en page. Si le fichier s'appelle "martian_data", le nom correct serait MartianDataBinding.
Tout le monde dit à propos de inflate()
, mais que se passe-t-il si nous voulons l’utiliser dans onViewCreated()
?
Vous pouvez utiliserbind(view)
méthode de la classe de liaison concrète pour obtenir une instance ViewDataBinding
pour la view
.
Habituellement nous écrivons BaseFragment quelque chose comme ceci (simplifié):
// BaseFragment.kt
abstract fun layoutId(): Int
override fun onCreateView(inflater, container, savedInstanceState) =
inflater.inflate(layoutId(), container, false)
Et utilisez-le dans un fragment d'enfant.
// 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)
}
Si tous les fragments utilisent la liaison de données, vous pouvez même simplifier l'utilisation du paramètre type.
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)
}
}
Je ne sais pas si je peux affirmer que non-null est valide ici, mais vous voyez l'idée. Si vous voulez que ce soit nul, vous pouvez le faire.