R
R
rocknow2017-09-10 17:55:00
Android
rocknow, 2017-09-10 17:55:00

What is the correct way to use Dagger 2 to pass a callback from an adapter to an activity/fragment?

I will say right away that we are talking about a new architecture presented at the latest Google IO.
At the moment, I have the following implementation:

public class ThumbnailsAdapterViewModel extends ViewModel {

    MutableLiveData<ThumbnailSelected> thumbnailSelectedMutableLiveData = new MutableLiveData<>();

    @Inject
    public ThumbnailsAdapterViewModel() {
    }

    public LiveData<ThumbnailSelected> getSelectedThumbnail() {
        return thumbnailSelectedMutableLiveData;
    }

    public void setThumbnailSelected(ThumbnailSelected thumbnailSelected) {
        thumbnailSelectedMutableLiveData.setValue(thumbnailSelected);
    }
}

Fragment, class member:
@Inject
ThumbnailsAdapter thumbnailsAdapter;

Fragment, onCreateView:
ThumbnailsAdapterViewModel thumbnailsAdapterViewModel = ViewModelProviders.of(this, viewModelFactory).get(ThumbnailsAdapterViewModel.class);
        thumbnailsAdapterViewModel.getSelectedThumbnail().observe(this, new Observer<ThumbnailSelected>() {
            @Override
            public void onChanged(@Nullable ThumbnailSelected thumbnailSelected) {
                if (thumbnailSelected != null) {
                    Snackbar.make(getView(), "Thumbnail #" + thumbnailSelected.getPosition() + " is selected", Snackbar.LENGTH_SHORT).show();
                }
            }
        });

thumbnailsAdapter.setViewModel(thumbnailsAdapterViewModel);

ThumbnailsAdapter:
public class ThumbnailsAdapter extends RecyclerView.Adapter<ThumbnailsAdapter.ViewHolder> {

    List<Thumbnail> thumbnails;
    private ThumbnailsAdapterViewModel viewModel;

    @Inject
    public ThumbnailsAdapter(List<Thumbnail> thumbnails) {
        this.thumbnails = thumbnails;
    }

    public void setViewModel(ThumbnailsAdapterViewModel viewModel) {
        this.viewModel = viewModel;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_thumbnail, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.bindData(thumbnails.get(position), position);
    }

    @Override
    public int getItemCount() {
        return thumbnails.size();
    }

    class ViewHolder extends RecyclerView.ViewHolder {
         // ... implementation

    public void bindData(final Thumbnail thumbnail, final int position) {
           
            imageThumbnail.setImageResource(R.drawable.ic_thumbnail);
          
            imageThumbnail.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    viewModel.setThumbnailSelected(new ThumbnailSelected(thumbnail, position));
                }
            });
        }
    }
}

The main disadvantage: I explicitly pass the ViewModel to the Adapter, but I can’t inject it, because if the dagger does this, then the model is created with a different scope (this is my assumption, I’m new to the dagger).
A couple more dagger classes:
@Module
public class ActivityModuleScopeMain {

    @Provides
    List<Thumbnail> provideThumbnails() {
        List<Thumbnail> thumbnails = new ArrayList<>();
        // тут создается список
        return thumbnails;
    }
}

@Module
public abstract class ActivityModuleMain {

    @ContributesAndroidInjector(modules = ActivityModuleScopeMain.class)
    abstract MainFragment contributeMainFragment();
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
R
rocknow, 2017-09-12
@rocknow

I dug into the example, I found an adapter there .

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question