with uso tutorial studio iniciar inicializar fragments android android-fragments android-databinding

android - uso - Cómo usar el enlace de datos con Fragment



navigation with fragments android (12)

Estoy tratando de seguir el ejemplo de enlace de datos del documento oficial de Google https://developer.android.com/tools/data-binding/guide.html

excepto que estoy tratando de aplicar la transferencia de datos a un fragmento, no a una actividad.

el error que obtengo actualmente al compilar es

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

onCreate for fragment se ve así:

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

onCreateView para fragmento se ve así:

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

y partes de mi archivo de diseño para fragmentos se ven así:

<?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>

mi sospecha es que MartianDataBinding no sabe con qué archivo de diseño debe estar vinculado, de ahí el error. ¿Alguna sugerencia?


Como la mayoría ha dicho, pero no se olvide de configurar LifeCycleOwner
Muestra en Java es decir

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


En realidad, se le recomienda utilizar el método de inflate de su enlace generado y no el 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(); }

Documentos para DataBindingUtil.inflate () :

Use esta versión solo si layoutId es desconocido de antemano. De lo contrario, utilice el método de inflado de Binding generado para garantizar una inflación segura.


Incluso las otras respuestas pueden funcionar bien, pero quiero decir el mejor enfoque.

Utilice el Binding class''s inflate como se recomienda en la documentación de Android .

Una opción es inflar por DataBindingUtil pero cuando solo usted no sabe que ha generado la clase de enlace .

- Tiene una binding class generada automáticamente, use esa clase en lugar de usar DataBindingUtil .

En java

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

En kotlin

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

En la documentation clase DataBindingUtil puede ver.

inflar

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; }

Use esta versión solo si layoutId es desconocido de antemano. De lo contrario, utilice el método de inflado de Binding generado para garantizar una inflación segura.

Si su clase de agrupación de diseño no se genera @Vea documentation .


La implementación del enlace de datos debe estar en el método onCreateView del fragmento, elimine cualquier enlace de datos que exista en su método OnCreate , su onCreateView debería verse así:

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; }


Otro ejemplo en 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 }

Tenga en cuenta que el nombre "MartianDataBinding" depende del nombre del archivo de diseño. Si el archivo se llama "martian_data", el nombre correcto sería MartianDataBinding.


Prueba esto en Android DataBinding

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 }


Si está utilizando ViewModel y LiveData Esta es la sintaxis suficiente

Sintaxis de Kotlin:

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


Todos dicen sobre inflate() , pero ¿qué pasa si queremos usarlo en onViewCreated() ?

Puede usar el método de bind(view) de la clase de enlace concreto para obtener la instancia de ViewDataBinding para la view .


Por lo general, escribimos BaseFragment de esta manera (simplificado):

// BaseFragment.kt abstract fun layoutId(): Int override fun onCreateView(inflater, container, savedInstanceState) = inflater.inflate(layoutId(), container, false)

Y úsalo en un fragmento infantil.

// 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 todos los Fragmentos usan enlace de datos, incluso puede simplificarlo usando el parámetro tipo.

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) } }

No sé si está bien afirmar que no es nulo allí, pero ... entiendes la idea. Si quieres que sea anulable, puedes hacerlo.


Un ejemplo completo en Fragmentos de enlace de datos

FragmentMyProgramsBinding es una clase de enlace generada para 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); } }


Uno simplemente puede recuperar el objeto de vista como se menciona a continuación

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; }


trabajando en mi código

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


Sintaxis de 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 }