2017-05-26 18 views
11

Tôi đang theo dõi this tài liệu để tìm hiểu về LiveData và ViewModel. Trong doc, lớp ViewModel có nhà xây dựng như vậy,Android ViewModel không có hàm tạo đối số 0

public class UserModel extends ViewModel { 
    private MutableLiveData<User> user; 

    @Inject UserModel(MutableLiveData<User> user) { 
    this.user = user; 
    } 

    public void init() { 
    if (this.user != null) { 
     return; 
    } 
    this.user = new MutableLiveData<>(); 
    } 

    public MutableLiveData<User> getUser() { 
    return user; 
    } 
} 

Tuy nhiên, khi tôi chạy mã, tôi nhận được ngoại lệ:

final UserViewModelviewModel = ViewModelProviders.of(this).get(UserViewModel.class); 

Nguyên nhân: java.lang.RuntimeException: Không thể tạo một thể hiện của lớp UserViewModel Gây ra bởi: java.lang.InstantiationException: java.lang.Class không có hàm tạo đối số bằng không

Trả lời

15

Trong khi khởi tạo các lớp con của ViewModel sử dụng ViewModelProviders, theo mặc định, nó sẽ yêu cầu lớp UserModel của bạn có hàm tạo đối số 0. Trong trường hợp của bạn constructor của bạn có lập luận MutableLiveData<User> user

Một cách để sửa lỗi này là có một mặc định không có constructor arg cho bạn UserModel

Nếu không, nếu bạn muốn có một constructor không zero luận cho lớp ViewModel của bạn, bạn có thể phải tạo một lớp ViewModelFactory tùy chỉnh để khởi tạo cá thể ViewModel của bạn, sẽ thực hiện giao diện ViewModelProvider.Factory.

Tôi chưa thử điều này nhưng đây là liên kết đến mẫu tuyệt vời từ google cho cùng: github.com/googlesamples/android-architecture-components. Cụ thể kiểm lớp này GithubViewModelFactory.java

+1

Thảo luận xung quanh này: https://www.reddit.com/ r/androiddev/comments/6bw1jj/architecture_components_introduction_google_io_17 / –

1

ViewModelFactory rằng sẽ cung cấp cho chúng ta một ViewModel ngay từ ViewModelModule

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

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

    @Override 
    public <T extends ViewModel> T create(Class<T> modelClass) { 
     Provider<ViewModel> viewModelProvider = viewModels.get(modelClass); 

     if (viewModelProvider == null) { 
      throw new IllegalArgumentException("model class " + modelClass + " not found"); 
     } 

     return (T) viewModelProvider.get(); 
    } 
} 

ViewModelModule có trách nhiệm ràng buộc khắp nơi trên lớp ViewModel vào
Map<Class<? extends ViewModel>, Provider<ViewModel>> viewModels

@Module 
public abstract class ViewModelModule { 

    @Binds 
    @IntoMap 
    @ViewModelKey(UserViewModel.class) 
    abstract ViewModel userViewModel(UserViewModel userViewModel); 

    //Others ViewModels 
} 

ViewModelKey là một chú thích để sử dụng làm khóa trong Bản đồ và trông giống như

@Target(ElementType.METHOD) 
@Retention(RetentionPolicy.RUNTIME) 
@MapKey 
@interface ViewModelKey { 
    Class<? extends ViewModel> value(); 
} 

Bây giờ bạn có thể tạo các ViewModel và làm hài lòng tất cả phụ thuộc cần thiết từ đồ thị

public class UserViewModel extends ViewModel { 
    private UserFacade userFacade; 

    @Inject 
    public UserViewModel(UserFacade userFacade) { // UserFacade should be defined in one of dagger modules 
     this.userFacade = userFacade; 
    } 
} 

instantiating ViewModel

public class MainActivity extends AppCompatActivity { 

    @Inject 
    ViewModelFactory viewModelFactory; 
    UserViewModel userViewModel; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     ((App) getApplication()).getAppComponent().inject(this); 

     userViewModel = ViewModelProviders.of(this, viewModelFactory).get(UserViewModel.class); 

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