Trying to run method in a layout file from my view model but, I keep getting error: cannot find symbol class ViewModels from my layout file. The layout file is a fragment. I tried invalidating the cache and resyncing but, it did not help. Do i need to add anything to the fragment itself? I seen people use data binding to launch the fragment but, I've read its optional.
Update: Took out OnClick method to test and it is still throwing error. I guess the problem is with my deceleration but, idk why. When i am editing the layout the path shows up when I type the view model name in.
Update2: Tried setting type in variable equal to path of activity that launches fragment for testing and it built just fine. There must be a way to add an import that is not my activity.
Layout file
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="viewTest"
type="rangers.socmanv2.ViewModels.BattleRhythmViewModel" />
</data>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/battleRhythmMenu"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Fragments.BattleRhythmFrag">
<Button
android:id="#+id/newBattle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="76dp"
android:layout_marginLeft="76dp"
android:layout_marginTop="88dp"
android:text="New Battle Rhythm"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<Button
android:id="#+id/editBattle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="76dp"
android:layout_marginLeft="76dp"
android:layout_marginTop="50dp"
android:text="Edit Battle Rhythm"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/newBattle" />
<Button
android:id="#+id/deleteBattle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="76dp"
android:layout_marginLeft="76dp"
android:layout_marginTop="50dp"
android:text="Delete Battle Rhythm"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/editBattle" />
</android.support.constraint.ConstraintLayout>
</layout>
Fragment
public class BattleRhythmFrag extends Fragment {
private BattleRhythmViewModel mViewModel;
private View view;
private Button test;
public static BattleRhythmFrag newInstance() {
return new BattleRhythmFrag();
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.battle_rhythm_fragment, container, false);
mViewModel = new BattleRhythmViewModel();
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = ViewModelProviders.of(this).get(BattleRhythmViewModel.class);
// TODO: Use the ViewModel
}
}
View model
public class BattleRhythmViewModel extends ViewModel {
public void launchNewFragment(FragmentManager fragM)
{
Log.d("viewmodel","hitting launchNewFrag");
HomeFrag test = new HomeFrag();
fragM.beginTransaction().replace(R.id.homeContent,test,"launched"+test);
}
public void test()
{Log.d("viewmodel","hitting test");
}
}
Your error is in viewModel constructor.
you must add a default constructor beacuse you don't added any factory ViewModelProvider.Factory but your BattleRhythmViewModel dosen't have any default constructor.
ANSWER 1:
public class BattleRhythmViewModel extends ViewModel {
public void launchNewFragment(){
}
public void test()
{Log.d("viewmodel","hitting test");
}
}
}
ANSWER 2: better than answer 1 beacuse you don't need add default and can use your fragment in model
public class Factory implements ViewModelProvider.Factory {
private FragmentManager fragM;
public Factory(FragmentManager fragM) {
this.fragM= fragM;
}
#NonNull
#Override
public <T extends ViewModel> T create(#NonNull Class<T> modelClass) {
if (modelClass.isAssignableFrom(BattleRhythmViewModel.class)) {
return (T) new BattleRhythmViewModel(fragM);
}
throw new IllegalArgumentException("Unknown ViewModel class");
}
}
change your viewmodel creator line to
Factory factory = new Factory(this)
mViewModel = ViewModelProviders.of(this,factory).get(BattleRhythmViewModel.class);
Related
I am creating a time prompter app for a sport activity. Not able to move back from Settings Fragment to Launcher Fragment. The code is similar to code that moves back from Action Fragment to Launcher Fragment successfully. I am getting error here that findNavController in NavHostFragment cannot be applied to SettingsFragment. It also says SettingsFragment cannot be converted to Fragment.
public void onClick(View view) {
NavHostFragment.findNavController(SettingsFragment.this)
.navigate(R.id.action_SettingsFragment_to_LauncherFragment);
public class SettingsFragment extends Fragment {
private FragmentSettingsBinding binding;
#Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
binding = FragmentSettingsBinding.inflate(inflater, container, false);
return binding.getRoot();
}
public void onViewCreated(#NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.goBackButtonSettings.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
NavHostFragment.findNavController(SettingsFragment.this)
.navigate(R.id.action_SettingsFragment_to_LauncherFragment);
}
});
}
}
SettingsFragment xml is below
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:contentDescription="#string/start_action"
android:foregroundTint="#color/teal_700"
android:textAlignment="center"
tools:context=".SettingsFragment">
<Button
android:id="#+id/goBackButtonSettings"
android:layout_width="65dp"
android:layout_height="54dp"
android:layout_marginBottom="24dp"
android:background="#color/teal_200"
android:backgroundTint="#F57F17"
android:text="#string/goback"
android:textColor="#color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.96"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Not able to locate where exactly the code is wrong and fix it. Need help.
I am an Android programming beginner. Appears my problem is simple and silly, still not able to locate the issue.
In the fragment, my objective is to show a dot every second which helps prompting someone to do some physical action, but no way near that. I am moving bit by bit and got struct at the first level itself.
public class ActionFragment extends Fragment {
private FragmentActionBinding binding;
TextView pCycleNum;
int pCycle;
#Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
View v = inflater.inflate(R.layout.fragment_action, container, false);
pCycleNum = v.findViewById(R.id.pCN);
pCycleNum.setText(String.valueOf(1));
binding = FragmentActionBinding.inflate(inflater, container, false);
return binding.getRoot();
}
public void onViewCreated(#NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.buttonSecond.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
NavHostFragment.findNavController(ActionFragment.this)
.navigate(R.id.action_ActionFragment_to_LauncherFragment);
}
});
binding.buttonAction.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
pCycleNum.setText("5");
}
});
}
I am setting pCycleNum to 5. But when I run the app on emmulator, it does not show any change. Not able to find out where I am going wrong.
The fragment xml is as follows
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:foregroundTint="#color/teal_700"
tools:context=".ActionFragment">
<Button
android:id="#+id/button_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/teal_200"
android:backgroundTint="#F57F17"
android:text="#string/goback"
android:textColor="#color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.96"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/textview_second"
app:layout_constraintVertical_bias="0.96" />
<TextView
android:id="#+id/textview_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#color/teal_700"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/buttonAction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="178dp"
android:layout_marginStart="139dp"
android:layout_marginTop="33dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.13"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.97" />
<TextView
android:id="#+id/pCN"
android:layout_width="174dp"
android:layout_height="112dp"
android:layout_marginStart="80dp"
android:layout_marginTop="130dp"
android:text="1"
android:textColor="#color/teal_200"
android:textSize="96sp"
android:visibility="visible"
app:layout_constraintStart_toEndOf="#+id/imageView13"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Please help to me to locate the error why app not displaying the set value. Also help me to understand why it is doing so. Thanks.
Just remove these lines from onCreateView() method.
View v = inflater.inflate(R.layout.fragment_action, container, false);
pCycleNum = v.findViewById(R.id.pCN);
pCycleNum.setText(String.valueOf(1));
And then use binding.pCN.setText("5");
This happened because you are using both findViewById() and view binding simulataneously.
And you are returning the binding in onCreateView() method. And onViewCreated() method don't know from where to get this pCN text view so it just skips.
you got a textview by id from v layout but then inflated a new layout, gave its reference to binding and returned the binding view not the view you used findViewById on
to avoid this mistake afterwards, just get your views from the binding object, you'll find them all by their id names (without any underscore character "_") like I did in binding.pCN
public class ActionFragment extends Fragment {
private FragmentActionBinding binding;
TextView pCycleNum;
int pCycle;
#Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
binding = FragmentActionBinding.inflate(inflater, container, false);
pCycleNum =binding.pCN;
return binding.getRoot();
}
public void onViewCreated(#NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.buttonSecond.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
NavHostFragment.findNavController(ActionFragment.this)
.navigate(R.id.action_ActionFragment_to_LauncherFragment);
}
});
binding.buttonAction.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
pCycleNum.setText("5");
}
});
}
Can someone suggest me the best way to call a fragment function from the RecyclerView without causing any memmory leaks
My fragment code is given below
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.auth.AuthActivity">
<com.google.android.exoplayer2.ui.PlayerView
android:id="#+id/videoID"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black"
app:resize_mode="fill"
app:controller_layout_id="#layout/player_control_view"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/materialList"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/videoID">
</androidx.recyclerview.widget.RecyclerView>
</androidx.constraintlayout.widget.ConstraintLayout>
My recycler view layout is
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="#dimen/_10sdp">
<androidx.cardview.widget.CardView
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:cardBackgroundColor="#color/circle_color_light"
app:layout_constraintVertical_bias="0.6">
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
/>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
Please ignore any error on the above layouts since my issue lies on java code
My fragment code is given below
public class MaterialFragment extends DaggerFragment implements View.OnClickListener {
SimpleExoPlayer player;
PlayerView playerView;
#Inject
MaterialAdapter adapter;
#Inject
ViewModelProviderFactory providerFactory;
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
makeVideo("https://samplevideo.com/test.mp4");
materialList = view.findViewById(R.id.materialList);
GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(),3,GridLayoutManager.VERTICAL,false);
materialList.setLayoutManager(gridLayoutManager);
materialList.setAdapter(adapter);
// The above code succesfully load the grid view using recycler adapter(Code for adapter is given below)
}
public void makeVideo(){
// Video loading code goes here : Loads video on findViewById(R.id.videoID)
}
}
Finally my Recycler Adapter view
public class MaterialAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = "MaterialAdapter";
private List<Material> materials = new ArrayList<>();
private Context context;
public MaterialAdapter(){
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.material_grid_layout, parent, false);
PlayerView playerView = ((Activity)parent.getContext()).getWindow().getDecorView().findViewById(R.id.matVideo);
SimpleExoPlayer player = new SimpleExoPlayer.Builder(((Activity)parent.getContext()).getApplicationContext()).build();
context = parent.getContext();
return new MaterialAdapter.MaterialViewHolder(view,parent.getContext(),playerView,player);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
((MaterialAdapter.MaterialViewHolder)holder).bind(materials.get(position),context);
}
#Override
public int getItemCount() {
return materials.size();
}
public void setMaterials(List<Material> materials){
this.materials = materials;
notifyDataSetChanged();
}
public class MaterialViewHolder extends RecyclerView.ViewHolder {
TextView name,letter;
public Context cxt;
private SimpleExoPlayer player;
private PlayerView playerView;
public MaterialViewHolder(#NonNull View itemView, Context cxt, final PlayerView playerView, SimpleExoPlayer player) {
super(itemView);
this.cxt = cxt;
this.playerView = playerView;
this.player = player;
name = itemView.findViewById(R.id.name);
clayout = (ConstraintLayout) itemView.findViewById(R.id.card_layout);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// I need to change the video of the fragment on click of each block.
//The below code will work by implementing full makevideo function on this file
//But I need the bes method without repeting this function and call the methods of he fragment by passing video url or setting view contents of the outer fragment
//makeVideo("https://samplevideo.com/test.mp4"); // Not think this is he best solution as I need fullscreen function also.
// How to trigger button click of fragment, eg full screen
}
});
}
public void bind(Material material, Context context){
name.setText(material.getName());
}
}
}
Adapter is injected using module as given below
#Provides
static MaterialAdapter provideMaterialAdapter(){
return new MaterialAdapter();
}
After referring, I got some suggestion by using my own interface as a bridge between adapter and fragment , But It didn't work may be my dagger is causing some injection error,
Can someone give me a best solution to get rid of this issue
Screenshot of my screen is given below
Use this adapter = new MaterialAdapter(); in your fragment rather than injecting it. Just remove the #Inject annotation and add the above adapter creation statement in onViewCreated of your fragment. By this way your get more control on your adapter creation and you can pass an interface through the constructor.
I want to use onClick method in fragment but data binding doesn't see method.
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
FragmentTodayBinding fragmentTodayBinding = DataBindingUtil.inflate(inflater,R.layout.fragment_today, container, false);
View view = fragmentTodayBinding.getRoot();
final MainViewModel mainViewModel = ViewModelProviders.of(this).get(MainViewModel.class);
fragmentTodayBinding.setMainViewModel(mainViewModel);
fragmentTodayBinding.searchButton.setOnClickListener(this::onSearchClick);
});
return view;
}
#Override
public void onSearchClick(View v) {
mainViewModel.getCity();
Toast.makeText(getActivity(), "X", Toast.LENGTH_SHORT).show();
}
Button xml:
<Button
android:id="#+id/search_button"
android:onClick="#{(v)-> todayFragmentInterface.onSearchClick(v)}"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentEnd="true"
android:layout_marginEnd="10dp"
android:layout_marginTop="5dp"
android:background="#drawable/ic_search_white_24dp" />
How to use it properly in fragment?
Follow this step:
1) Add this line in onCreateView
fragmentTodayBinding.fragment = this;
2) Add this line in your layout.xml
<variable name="fragment" type="yourPackage.ClassName" />
3) Edit onClick in xml with
android:onClick="#{(v)-> fragment.onSearchClick(v)}"
You can also remove:
fragmentTodayBinding.searchButton.setOnClickListener(this::onSearchClick);
I saw that you use #Override so needs an Interface, the goal is the same, just use variable interface in the xml variable (and refer to it with package of interface), than use fragmentTodayBinding.myInterface = this;
So:
1) fragmentTodayBinding.myInterface = this;
2) <variable name="myInterface" type="yourPackage.Interface" />
3) android:onClick="#{(v)-> myInterface.onSearchClick(v)}"
I would like to create a gridview of movie posters images with using bindings.
My viewmodel looks like that:
public class PopularMoviesViewModel extends BaseObservable {
Movie movie;
Context context;
MovieServiceComponent movieServiceComponent = DaggerMovieServiceComponent.builder()
.contextModule(new ContextModule(context))
.build();
Picasso getPicasso = movieServiceComponent.getPicasso();
public PopularMoviesViewModel(Movie movie, Context context) {
this.movie = movie;
this.context = context;
}
#Bindable
public String getImageUrl(){
return movie.posterPath();
}
#Bindable
public String getTitle(){
return movie.originalTitle();
}
#BindingAdapter({"imageUrl"})
public void setImageUrl(ImageView view, String poserPath){
getPicasso.with(view.getContext()).load("http://image.tmdb.org/t/p/w185"+ poserPath).into(view);
}
}
Layout:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<data class="PopularMoviesBinding">
<variable
name="pmvm"
type="com.hartyandi.oviesm.modelviews.PopularMoviesViewModel"></variable>
</data>
<LinearLayout
android:id="#+id/row"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
android:paddingBottom="0dp"
android:paddingTop="5dp"
android:paddingRight="2.5dp"
android:paddingLeft="5dp"
android:orientation="vertical">
<ImageView
app:imageUrl="#{pmvm.imageUrl}"
android:id="#+id/popular_movies_grid_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="0dp"
android:adjustViewBounds="true"
android:elevation="20dp">
</ImageView>
<TextView
android:id="#+id/popular_movies_grid_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{pmvm.title}"
android:textColor="#000000"
android:textSize="12sp"
android:background="#FFFFFF"
>
</TextView>
</LinearLayout>
</layout>
Adapter:
public class PopularMoviesAdapter extends RecyclerView.Adapter<PopularMoviesAdapter.BindingHolder> {
private List<Movie> movies;
private Context context;
public PopularMoviesAdapter(List<Movie> movies, Context context) {
this.movies = movies;
this.context = context;
}
public void add(Movie movie){
movies.add(movie);
}
#Override
public BindingHolder onCreateViewHolder(ViewGroup parent, int viewType) {
PopularMoviesBinding popularMoviesBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),
R.layout.popular_movies_gridview_row, parent,false);
return new BindingHolder(popularMoviesBinding);
}
#Override
public void onBindViewHolder(PopularMoviesAdapter.BindingHolder holder, int position) {
PopularMoviesBinding popularMoviesBinding = holder.popularMoviesBinding;
popularMoviesBinding.setPmvm(new PopularMoviesViewModel(movies.get(position), context));
}
#Override
public int getItemCount() {
return movies.size();
}
public class BindingHolder extends RecyclerView.ViewHolder{
private PopularMoviesBinding popularMoviesBinding;
public BindingHolder(PopularMoviesBinding popularMoviesBinding) {
super(popularMoviesBinding.getRoot());
this.popularMoviesBinding = popularMoviesBinding;
}
}
}
I get the following error:
java.lang.IllegalStateException: Required DataBindingComponent is null in class PopularMoviesBinding.A BindingAdapter in modelviews.PopularMoviesViewModel is not static and requires an object to use, retrieved from the DataBindingComponent.
I tried to change my implementation just like this stackoverflow post suggest and I got the same error message.
I also used the following code as example.
Could someone explain what the problem with the code, and how to solve it?
You probably didn't intend to use an instance method for the BindingAdapter.
If you do, you must provide a DataBindingComponent so that the generated Binding class knows which instance to use.
You have two options -- provide a DataBindingComponent or just pass the required context as an attribute to a static binding adapter method. The second is a bit easier to understand, so I'll start with that:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<data class="PopularMoviesBinding">
<variable name="pmvm"
type="com.hartyandi.oviesm.modelviews.PopularMoviesViewModel"/>
<variable name="picasso" type="com.whatever.Picasso"/>
</data>
<!-- ... -->
<ImageView
app:imageUrl="#{pmvm.imageUrl}"
app:picasso="#{picasso}"
... />
</ImageView>
</layout>
Then in your BindingAdapter:
#BindingAdapter({"imageUrl", "picasso"})
public static void setImageUrl(ImageView view, String poserPath, Picasso picasso){
picasso.with(view.getContext()).load("http://image.tmdb.org/t/p/w185"+ poserPath).into(view);
}
Note that setImageUrl is now static.
Alternatively, since your the Picasso instance is also on the ViewModel, you can just pass the instance by adding a getter for the picasso:
<ImageView
app:imageUrl="#{pmvm.imageUrl}"
app:picasso="#{pmvm.picasso}"
... />
and the method in your ViewModel:
public Picasso getPicasso() { return this.getPicasso; }
The other way means that you implement a DataBindingComponent. When you create an instance BindingAdapter method, the generated interface will have a getter for your class. You'll need to create a class to implement that interface:
public class MyDataBindingComponent implements DataBindingComponent {
public PopularMoviesViewModel getPopularMoviesViewModel() {
return whateverIDoToCreateOrGetThisBindingAdapterInstance();
}
}
Then you pass the instance when you inflate or bind:
PopularMoviesBinding popularMoviesBinding =
DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),
R.layout.popular_movies_gridview_row, parent,false,
new MyDataBindingComponent());
just make the setImageUrl() method static to be like this code
#BindingAdapter({"imageUrl"})
public void setImageUrl(ImageView view, String poserPath){
getPicasso.with(view.getContext()).load("http://image.tmdb.org/t/p/w185"+
poserPath).into(view);
}