2017-06-20 16 views
8

Tôi đang cố gắng sử dụng Cấu phần Kiến trúc mới, nhưng tôi cũng vẫn còn mới để dagger và tôi đang thiếu nội dung.Cách sử dụng đúng Dagger2 với Cấu phần Kiến trúc Android mới

Với mã bên dưới, tôi nhận được NullPointerException, không thể xác định vị trí. Ngoài ra nếu có điều gì khác mà tôi cần sửa chữa hoặc cải thiện, vui lòng đề xuất.

Mã sản phẩm: ViewModel

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

Repository

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

Sau đó, trong 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) 
+0

bạn đã gọi InjectorClass.inject (this) trong onCreate hoạt động của bạn chưa? –

+0

@OrestSavchak, không có tôi, cái gì là 'InjectorClass' – Relm

+0

Tôi có nghĩa là bạn tạo ra trường hợp ViewModelFactory ở đâu? –

Trả lời

1

Vấn đề là do cá thể ViewModelFactory bị thiếu trong số MainActivity của bạn, như NPE gợi ý. Điều này chính nó có thể là do thực tế là ViewModelFactory không được tiêm đúng cách, do đó còn lại null. Như Orest cho thấy bên trong bình luận, bạn cần phải chắc chắn rằng MainActivity được tiêm đúng từ AppModule của bạn:

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

Bạn có thể có một cái nhìn tại hầu hết các lớp DI đang được sử dụng trong một câu hỏi liên quan mà tôi đã đăng trước đó qua số AndroidInjector<android.app.Activity> cannot be provided without an @Provides- or @Produces-annotated method và xem liệu thiết lập đó có giúp ích cho bạn hay không.

Các vấn đề liên quan