如何在新的Android架构组件中正确使用Dagger2

时间:2017-06-20 11:03:40

标签: java android dagger-2 model-view android-architecture-components

我试图使用新的架构组件,但我还是匕首新手,而且我缺少了东西。

使用下面的代码,我得到一个NullPointerException,无法找到位置。 此外,如果我需要修复或改进其他内容,请建议。

代码:视图模型

public class PostsVM extends ViewModel {
    private LiveData<StoryPost> post;
    private Repository          repository;

    @Inject
    public PostsVM(Repository repository) {
        this.repository = repository;
    }

    public void init() {
        if (this.post != null) {
            return;
        }
        post = repository.getPosts();
    }

    public LiveData<StoryPost> getPost() {
        return post;
    }
}

存储库

@Singleton
public class Repository {
    private final MutableLiveData<StoryPost> data = new MutableLiveData<>();

    public LiveData<StoryPost> getPosts() {
        //
        new GetUser(post.getUid()) {
            @Override
            public void onSuccess(@NonNull User user) {
                // this is where I setValue//
                data.setValue(post);
        }

        @Override
        public void onError() {

        }

        @Override
        public void userNotFound() {

        }
    };
    return data;
    }
}

Singleton Factory

@Singleton
public class ViewModelFactory implements ViewModelProvider.Factory {
private final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators;

@Inject
public ViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
    this.creators = creators;
}

@SuppressWarnings("unchecked")
@Override
public <T extends ViewModel> T create(Class<T> modelClass) {
    Provider<? extends ViewModel> creator = creators.get(modelClass);
    if (creator == null) {
        for (Map.Entry<Class<? extends ViewModel>, Provider<ViewModel>> entry : creators.entrySet()) {
            if (modelClass.isAssignableFrom(entry.getKey())) {
                creator = entry.getValue();
                break;
            }
        }
    }
    if (creator == null) {
        throw new IllegalArgumentException("unknown model class " + modelClass);
    }
    try {
        return (T) creator.get();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

}

DAO

@Dao
public interface PostDao {
    @Query("SELECT * FROM posts ORDER by time DESC")
    LiveData<List<StoryPost>> getAll();

    @Query("SELECT * FROM posts WHERE id = :id")
    LiveData<List<StoryPost>> getPost(String id);

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    @NonNull
    void insert(StoryPost... posts);

    @Delete
    void delete(StoryPost post);

    @Update
    void update(StoryPost post);
}

然后在MainActivity中:

@Inject public ViewModelFactory factory;
//...
//*onCreate*

PostsVM model = ViewModelProviders.of(this, factory).get(PostsVM.class);
model.init();
final Observer<StoryPost> observer = post -> storyAdapter.insert(post);
model.getPost().observe(this, observer);

Logcat

... java.lang.NullPointerException: Attempt to invoke interface method 
'android.arch.lifecycle.ViewModel android.arch.lifecycle.ViewModelProvider
$Factory.create(java.lang.Class)' on a null object reference
                                                                              at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2479)
                                                                              at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2539)
                                                                              at android.app.ActivityThread.access$900(ActivityThread.java:168)
                                                                              at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1378)
                                                                              at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                              at android.os.Looper.loop(Looper.java:150)
                                                                              at android.app.ActivityThread.main(ActivityThread.java:5665)
                                                                              at java.lang.reflect.Method.invoke(Native Method)
                                                                             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:799)
                                                                              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:689)
                                                                           Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'android.arch.lifecycle.ViewModel android.arch.lifecycle.ViewModelProvider$Factory.create(java.lang.Class)' on a null object reference
                                                                           at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:128)
                                                                              at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:96)
                                                                              at com.aollay.smartpaper.MainActivity.bindDatabase(MainActivity.java:238)
                                                                              at com.aollay.smartpaper.MainActivity.populateNews(MainActivity.java:233)
                                                                              at com.aollay.smartpaper.MainActivity.config(MainActivity.java:159)
                                                                              at com.aollay.smartpaper.MainActivity.onCreate(MainActivity.java:74)
                                                                              at android.app.Activity.performCreate(Activity.java:6372)
                                                                              at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110)
                                                                              at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2432)

1 个答案:

答案 0 :(得分:2)

问题是由于ViewModelFactory实例在MainActivity内为空,正如NPE所暗示的那样。这本身很可能是因为ViewModelFactory未被正确注入,因此保持为空。正如Orest在评论中建议的那样,您需要确保从MainActivity正确注入AppModule

<强> MainActivity:

public class MainActivity extends AppCompatActivity implements HasSupportFragmentInjector
{
     @Override
     protected void onCreate(Bundle savedInstanceState)
     {
          AndroidInjection.inject(activity);
            super.onCreate(savedInstanceState);
     }

    // if your Activity also has Fragments which need to be injected

    @Inject
    DispatchingAndroidInjector<Fragment> androidInjector;

    @Override
    public DispatchingAndroidInjector<Fragment> supportFragmentInjector()
    {
        return androidInjector;
    }
}

您可以查看我之前在AndroidInjector<android.app.Activity> cannot be provided without an @Provides- or @Produces-annotated method发布的相关问题中使用的大多数DI类,并查看该设置是否可以帮助您解决问题。