package com.patloew.countries.ui.base; import android.databinding.DataBindingUtil; import android.databinding.ViewDataBinding; import android.support.annotation.NonNull; import android.support.v7.widget.RecyclerView; import android.view.View; import com.patloew.countries.BR; import com.patloew.countries.injection.components.DaggerViewHolderComponent; import com.patloew.countries.injection.components.ViewHolderComponent; import com.patloew.countries.ui.base.view.MvvmView; import com.patloew.countries.ui.base.viewmodel.MvvmViewModel; import com.patloew.countries.ui.base.viewmodel.NoOpViewModel; import com.patloew.countries.util.Utils; import javax.inject.Inject; /* Copyright 2016 Patrick Löwenstein * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * ------ * * FILE MODIFIED 2017 Tailored Media GmbH */ /* Base class for ViewHolders when using a view model with data binding. * This class provides the binding and the view model to the subclass. The * view model is injected and the binding is created when the content view is bound. * Each subclass therefore has to call the following code in the constructor: * viewHolderComponent().inject(this); * bindContentView(view); * * After calling these methods, the binding and the view model is initialized. * saveInstanceState() and restoreInstanceState() are not called/used for ViewHolder * view models. * * Your subclass must implement the MvvmView implementation that you use in your * view model. */ public abstract class BaseViewHolder<B extends ViewDataBinding, V extends MvvmViewModel> extends RecyclerView.ViewHolder { protected B binding; @Inject protected V viewModel; protected final View itemView; private ViewHolderComponent viewHolderComponent; public BaseViewHolder(View itemView) { super(itemView); this.itemView = itemView; } protected final ViewHolderComponent viewHolderComponent() { if(viewHolderComponent == null) { viewHolderComponent = DaggerViewHolderComponent.builder() .activityComponent(Utils.castActivityFromContext(itemView.getContext(), BaseActivity.class).activityComponent()) .build(); } return viewHolderComponent; } protected final void bindContentView(@NonNull View view) { if(viewModel == null) { throw new IllegalStateException("viewModel must not be null and should be injected via viewHolderComponent().inject(this)"); } binding = DataBindingUtil.bind(view); binding.setVariable(BR.vm, viewModel); try { //noinspection unchecked viewModel.attachView((MvvmView) this, null); } catch(ClassCastException e) { if (!(viewModel instanceof NoOpViewModel)) { throw new RuntimeException(getClass().getSimpleName() + " must implement MvvmView subclass as declared in " + viewModel.getClass().getSimpleName()); } } } public final V viewModel() { return viewModel; } public final void executePendingBindings() { if(binding != null) { binding.executePendingBindings(); } } }