0

您好我正在使用MVVM和匕首2對我的應用程序進行重構,並且我正在關注這個示例[Countries App] [1] [1]: https://github.com/patloew/countries/tree/master/app不能在Android中使用匕首2和MVVM注入RecyclerView ViewHolder

我已經成功注入LoginActivity,RestAPi和其他,但在我的下一個活動中,我有一個回收站視圖,並且視圖持有者在編譯時出錯。 這是我的代碼:

組件

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

模塊

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

佈局 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> 

如果我評論的麟蹄在DiViewHolderComponent中的ct方法和視圖持有者的代碼編譯和啓動應用程序,我已經檢查了很多次的代碼,但我不知道問題出在哪裏,請大家幫忙!!!

錯誤日誌

/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

請包括實際的錯誤信息 –

+0

錯誤日誌添加 –

回答

0

好像你還沒有加入計提方法爲「父」組件即。 DiComponent。 試試這個:

@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*/ 
} 

不是您正在使用的模塊abstract class ViewModelModule,這似乎不可能的匕首知道注入哪個模塊。它應該只用於實現的類。

之後,清潔項目和建設。

地址:看官方示例項目https://github.com/google/dagger/tree/master/examples/android-activity-graphs