Как использовать привязку данных с фрагментом
Я пытаюсь следовать примеру привязки данных из официального документа google https://developer.android.com/tools/data-binding/guide.html
за исключением того, что я пытаюсь применить Data-biding к фрагменту, а не к действию.
ошибка, которую я сейчас получаю при компиляции
Error:(37, 27) No resource type specified (at 'text' with value '@{marsdata.martianSols}.
onCreate для фрагмента выглядит так:
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MartianDataBinding binding = MartianDataBinding.inflate(getActivity().getLayoutInflater());
binding.setMarsdata(this);
}
onCreateView для фрагмента выглядит так это:
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.martian_data, container, false);
}
и части моего файла макета для фрагмента выглядит так:
<?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>
Я подозреваю, что MartianDataBinding не знает, с каким файлом макета он должен быть связан-отсюда и ошибка. Есть предложения?
9 ответов:
реализация привязки данных должна быть в методе onCreateView фрагмента, удалите все привязки данных, которые существуют в вашем методе OnCreate , ваш onCreateView должен выглядеть так :
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; }
вы на самом деле рекомендуется использовать
inflateметод вашей сгенерированной привязки, а не 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(); }документы для DataBindingUtil.надуть():
используйте эту версию только в том случае, если layoutId заранее неизвестен. В противном случае используйте метод inflate сгенерированной привязки для обеспечения типобезопасной инфляции.
можно просто получить вид объекта, как указано ниже
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; }
попробуйте это в 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; }
работает в моем коде.
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(); }
даже другие ответы могут работать хорошо, но я хочу сказать лучший подход.
использовать
Binding class's inflateкак это рекомендовано в Документация Для Android.один из вариантов-раздуть на
DataBindingUtilно когда только вы не знаете, сгенерировали класс привязки.--вы вызвали
binding class, используйте этот класс вместо использованияDataBindingUtil.В 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 Котлин
lateinit var binding: HomeFragmentBinding override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { binding = HomeFragmentBinding.inflate(inflater, container, false) return binding.root }на DataBindingUtil класс документация вы можете видеть.
надуйте
T inflate (LayoutInflater inflater, int layoutId, ViewGroup parent, boolean attachToParent)используйте эту версию только в том случае, если layoutId заранее неизвестен. В противном случае используйте метод inflate сгенерированной привязки для обеспечения типобезопасности инфляция.
если ваш класс привязки макета не генерируется @See этот ответ.
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 }
еще один пример в Котлине:
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 }обратите внимание, что имя "MartianDataBinding" зависит от имени файла макета. Если файл называется "martian_data", то правильным именем будет MartianDataBinding.
полный пример в привязке данных фрагментов
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); } }
Comments