0

Salut, je fais un refactor de mon application avec MVVM et poignard 2, et je suis cet exemple [Countries App] [1] [1]: J'ai réussi à injecter LoginActivity, RestAPi et d'autres, mais dans ma prochaine activité, j'ai une vue recycleur et les détenteurs de vue donnent une erreur lors de la compilation. Ceci est mon code:Impossible d'injecter RecyclerView ViewHolder dans android avec dagger 2 et MVVM

Composants

@PerApplication 
@Component(modules = {AppModule.class, NetworkApiModule.class, ViewModelModule.class}) 
public interface DiComponent { 
    @AppContext 
    Context context(); 
    Resources resources(); 
    APIService apiService(); 
} 
@PerActivity 
@Component(dependencies = {DiComponent.class},modules ={ActivityModules.class, ViewModelModule.class}) 
public interface DiActivitiesComponent { 
    void inject(LoginActivity activity); 
    void inject(MainActivity activity); 
} 
@PerViewHolder 
@Component(dependencies = DiComponent.class, modules ={ViewHolderModule.class, ViewModelModule.class}) 
public interface DiViewHolderComponent { 
    void inject(MenuViewHolder viewHolder); 
} 

Modules

@Module 
public class AppModule { 
    private final Application mApp; 
    public AppModule(Application app) { 
    mApp = app; 
    } 
    @Provides 
    @PerApplication 
    @AppContext 
    Context provideAppContext() { 
     return mApp; 
    } 
    @Provides 
    @PerApplication 
    Resources provideResources(){return mApp.getResources();} 
} 
@Module 
public class ActivityModules { 
    private final BaseActivity baseActivity; 
    public ActivityModules(BaseActivity baseActivity) { 
    this.baseActivity = baseActivity; 
    } 
    @Provides 
    @PerActivity 
    @ActivityContext 
    Context provideActivityContext() { return baseActivity; } 

    @Provides 
    @PerActivity 
    ProgressDialog provideProgressDialog() { 
    ProgressDialog progress; 
    progress = new ProgressDialog(baseActivity); 
    progress.setMessage("Loading..."); 
    progress.setCancelable(false); 
    return progress; 
    } 
    @Provides 
    @PerActivity 
    Validator validator(){ 
    return new Validator(baseActivity); 
    } 
    @Provides 
    @PerActivity 
    Navigator provideNavigator() { return new ActivityNavigator(baseActivity); } 
} 
@Module 
public class ViewHolderModule { 

    private final AppCompatActivity activity; 
    public ViewHolderModule(View itemView) { 
    activity = (AppCompatActivity) itemView.getContext(); 
    } 
    @Provides 
    @PerViewHolder 
    @ActivityContext 
    Context provideActivityContext() { return activity; } 

    @Provides 
    @PerViewHolder 
    FragmentManager provideFragmentManager() { return activity.getSupportFragmentManager(); } 

    @Provides 
    @PerViewHolder 
    Navigator provideNavigator() { return new ActivityNavigator(activity); } 
} 
@Module 
public abstract class ViewModelModule { 
    @Binds 
    abstract Observable bindLoginViewModel(LoginViewModel loginViewModel); 
    @Binds 
    abstract Observable bindMainViewModel(MainViewModel mainViewModel); 

    @Binds 
    abstract MenuModelView bindCMenuViewModel(MenuModelView menuModelView); 
} 

Aplication

public class MyApplication extends Application { 
    private static MyApplication instance=null; 
    private static DiComponent component=null; 
    @Override 
    public void onCreate() { 
    super.onCreate(); 
    instance=this; 
    component = DaggerDiComponent.builder() 
      .appModule(new AppModule(this)) 
      .build(); 
    } 
    public static MyApplication getInstance(){ 
    return instance; 
    } 
    public static DiComponent getComponent() { 
    return component; 
    } 
    public static Resources getRes() { return instance.getResources(); } 
} 

BaseActivity

public abstract class BaseActivity<B extends ViewDataBinding,V extends MvvmViewModel> extends AppCompatActivity{ 
    public static final String TAG = "BaseActivity"; 
    protected B binding; 
    @Inject protected V viewModel; 
    @Inject protected Validator validator; 
    @Inject protected ProgressDialog progress; 
    private DiActivitiesComponent component; 

    protected final void setAndBindContentView(@LayoutRes int layoutResId, @Nullable Bundle savedInstanceState) { 
    if(viewModel == null) { throw new IllegalStateException("viewModel must not be null and should be injected via activityComponent().inject(this)"); } 
    binding = DataBindingUtil.setContentView(this, layoutResId); 
    binding.setVariable(BR.vm, viewModel); 
    viewModel.attachView((MvvmView) this, savedInstanceState); 
    } 
    protected final DiActivitiesComponent activityComponent() { 
    if(component == null) { 
     component = DaggerDiActivitiesComponent.builder() 
       .diComponent(MyApplication.getComponent()) 
       .activityModules(new ActivityModules(this)) 
       .build(); 
    } 
    return component; 
    } 
    @Override 
    @CallSuper 
    protected void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
    if(viewModel != null) { viewModel.saveInstanceState(outState); } 
    } 
    @Override 
    @CallSuper 
    protected void onDestroy() { 
    super.onDestroy(); 
    if(viewModel != null) { viewModel.detachView(); } 
    viewModel = null; 
    binding = null; 
    component = null; 
    } 
} 

MainActivity

public class MainActivity extends BaseBarActivity<ActivityMainBinding, MainViewModel> implements MvvmView { 
    @Inject MenuListAdapter adapter; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    activityComponent().inject(this); 
    setAndBindContentView(R.layout.activity_main, savedInstanceState); 
    loadToolbar(R.string.empty_title); 
    ButterKnife.bind(this); 

    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); 
    drawer.setDrawerListener(toggle); 
    toggle.syncState(); 

    binding.lstMenuItems.setHasFixedSize(true); 
    binding.lstMenuItems.setLayoutManager(new LinearLayoutManager(this)); 
    binding.lstMenuItems.setAdapter(adapter); 

    adapter.setMenuItems(menuItems); 
    adapter.notifyDataSetChanged(); 
    } 
} 

ViewModels BaseViewModel

public abstract class BaseViewModel<V extends MvvmView> extends BaseObservable implements MvvmViewModel<V> { 
    @Inject protected Provider<Navigator> navigator; 
    private V mView; 
    public V getView() { 
    return mView; 
    } 
    @Override 
    @CallSuper 
    public void attachView(@NonNull V view, @Nullable Bundle savedInstanceState) { 
    mView = view; 
    if(savedInstanceState != null) { restoreInstanceState(savedInstanceState); } 
    } 
    @Override 
    @CallSuper 
    public void detachView() { 
    mView = null; 
    } 
    @Override 
    public void saveInstanceState(@NonNull Bundle outState) { } 
    @Override 
    public void restoreInstanceState(@NonNull Bundle savedInstanceState) { } 
} 

MainViewModel

@PerActivity 
public class MainViewModel extends BaseViewModel<MvvmView> { 
    private Context context; 
    @Inject 
    public MainViewModel(@AppContext Context context) { 
    this.context=context; 
    }  
} 

ItemViewModel

@PerViewHolder 
public class MenuModelView extends BaseViewModel<MvvmView> { 
    private PegasusMenuItem item; 
    private final Context context; 
    @Inject 
    public MenuModelView(@AppContext Context context){ 
    this.context=context.getApplicationContext(); 
    } 
    @Bindable 
    public Drawable getImage() { 
    return AppCompatDrawableManager.get().getDrawable(context,item.getResId()); 
    } 
    public String getTextData() { 
    return item.getText(); 
    } 
    public void update(PegasusMenuItem item) { 
    this.item = item; 
    notifyChange(); 
    } 
} 

BaseViewHolder

public abstract class BaseViewHolder<B extends ViewDataBinding, V extends MvvmViewModel> extends RecyclerView.ViewHolder { 
    protected B binding; 
    @Inject protected V viewModel; 
    private DiViewHolderComponent viewHolderComponent; 
    private View itemView = null; 

    public BaseViewHolder(View itemView) { 
    super(itemView); 
    this.itemView = itemView; 
    } 
    protected final DiViewHolderComponent viewHolderComponent() { 
    if(viewHolderComponent == null) { 
     viewHolderComponent = DaggerDiViewHolderComponent.builder() 
       .diComponent(MyApplication.getComponent()) 
       .viewHolderModule(new ViewHolderModule(itemView)) 
       .build(); 
     itemView = null; 
    } 
    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); 
    viewModel.attachView((MvvmView) this, null); 
    } 
    public final V viewModel() { return viewModel; } 
} 

MenuViewHolder

public class MenuViewHolder extends BaseViewHolder<MenuItemBinding, MenuModelView> implements MvvmView { 
    public MenuViewHolder(View v) { 
    super(v); 
    viewHolderComponent().inject(this); 
    bindContentView(v); 
    } 
} 

Layouts activity_main

<layout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools"> 
    <data> 
    <variable name="vm" type="com.package.name.ViewModels.MainViewModel" /> 
    </data> 
    <android.support.v4.widget.DrawerLayout 
    android:id="@+id/drawer_layout" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:fitsSystemWindows="true" 
    tools:openDrawer="start"> 
     <include 
     layout="@layout/app_bar_main" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" /> 
     <android.support.design.widget.NavigationView 
     android:id="@+id/nav_view" 
     android:layout_marginTop="@dimen/activity_vertical_margin" 
     android:layout_width="@dimen/menu_item_size" 
     android:layout_height="match_parent" 
     android:layout_gravity="start" 
     android:fitsSystemWindows="true"> 

     <LinearLayout 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:background="@color/gray_color" 
      android:orientation="vertical"> 

      <android.support.v7.widget.RecyclerView 
       android:id="@+id/lst_menu_items" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       android:layout_weight="1" 
       android:dividerHeight="0dp" 
       android:divider="@null" /> 
     </LinearLayout> 
    </android.support.design.widget.NavigationView> 
    </android.support.v4.widget.DrawerLayout> 
</layout> 

menu_item

<layout xmlns:android="http://schemas.android.com/apk/res/android"> 
    <data> 
    <variable name="vm" type="com.package.name.ViewModels.ViewHolders.MenuModelView" /> 
    </data> 
    <RelativeLayout 
    android:layout_width="@dimen/menu_item_size" 
    android:layout_height="@dimen/menu_item_size" 
    android:paddingTop="@dimen/margin_fields" 
    android:paddingBottom="@dimen/margin_fields" 
    android:background="@color/gray_color"> 
     <ImageView 
     android:layout_width="@dimen/menu_item_icon_size" 
     android:layout_height="@dimen/menu_item_icon_size" 
     android:id="@+id/img_menu_icon" 
     android:src="@{vm.image}" 
     android:scaleType="centerInside" 
     android:layout_centerHorizontal="true" /> 
     <TextView 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:text="@{vm.textData}" 
     android:id="@+id/txt_menu_title" 
     android:textSize="@dimen/text_xsmall_size" 
     android:gravity="center" 
     android:layout_below="@+id/img_menu_icon" 
     android:textColor="@color/white_color" /> 
    </RelativeLayout> 
</layout> 

Si je commente le Inje ct méthodes dans DiViewHolderComponent et dans le titulaire de la vue le code compiler et lancer l'application, j'ai vérifié le code de nombreuses fois, mais je ne sais pas où est le problème s'il vous plaît aider !!!

Error Log

/Users/.../Views/Activities/BaseActivity.java 
Error:(20, 42) error: cannot find symbol class BR 
Error:(21, 63) error: cannot find symbol class DaggerDiActivitiesComponent 
/Users/.../Views/Activities/LoginActivity.java 
Error:(16, 54) error: package com.mifinity.app2soft.mifinitymvvm.databinding does not exist 
Error:(25, 49) error: cannot find symbol class LoginActivityBinding 
/Users/.../Views/Activities/MainActivity.java 
Error:(23, 54) error: package com.package.name.databinding does not exist 
Error:(30, 51) error: cannot find symbol class ActivityMainBinding 
/Users/.../Views/ViewHolders/BaseViewHolder.java 
Error:(9, 42) error: cannot find symbol class BR 
Error:(10, 63) error: cannot find symbol class DaggerDiViewHolderComponent 
/Users/.../Views/ViewHolders/MenuViewHolder.java 
Error:(7, 54) error: package com.package.name.databinding does not exist 
Error:(12, 53) error: cannot find symbol class MenuItemBinding 
/Users/.../Views/ViewHolders/LastTransactionsViewHolder.java 
Error:(7, 54) error: package com.mifinity.app2soft.mifinitymvvm.databinding does not exist 
Error:(12, 64) error: cannot find symbol class AccountItemBinding 
/Users/.../Views/ViewHolders/AmountViewHolder.java 
Error:(7, 54) error: package com.package.name.databinding does not exist 
Error:(13, 54) error: cannot find symbol class BalanceItemBinding 

/Users/.../Views/Fragments/BaseFragment.java 
Error:(18, 42) error: cannot find symbol class BR 
Error:(19, 63) error: cannot find symbol class DaggerFragmentComponent 
/Users/developer/22Technology/Android  Projects/.../Views/Fragments/OverviewFragment.java 
Error:(22, 54) error: package com.package.name.databinding does not exist 
Error:(33, 52) error: cannot find symbol class OverviewFragmentBinding 
/Users/.../MyApplication.java 
Error:(6, 63) error: cannot find symbol class DaggerDiComponent 
Note: Generating a MembersInjector for com.package.name.Views.Activities.MainActivity. Prefer to run the dagger processor over that class instead. 
Error:Execution failed for task ':app:compileDebugJavaWithJavac'. 
> java.lang.StackOverflowError 
+0

S'il vous plaît inclure le message d'erreur réelle –

+0

journal d'erreur ajouté –

Répondre

0

Il semble que vous ayez pas ajouter des méthodes de fourniture à-dire des composants "parent". DiComponent. Essayez ceci:

@PerApplication 
@Component(modules = {AppModule.class, NetworkApiModule.class, ViewModelModule.class}) 
public interface DiComponent { 
    @AppContext 
    Context context(); 
    Resources resources(); 
    APIService apiService(); 


    Context provideAppContext(); 
    Resources provideResources(); 
    /**etc. put other @provide 
    method interfaces of modules 
    which are other components dependent on here*/ 
} 

Que vous utilisez en tant que module abstract class ViewModelModule, qui ne semble pas possible pour Dague de savoir quel module injectent. Il devrait être utilisé uniquement les classes implémentées.

Après ce projet propre et Build.

Ajouter: Regardez l'exemple officiel des projets https://github.com/google/dagger/tree/master/examples/android-activity-graphs