我有这样的改造服务
public interface BrandsService {
@GET("listBrand")
Call<List<Brand>> getBrands();
}
然后我有一个存储库来从这样的 api 获取数据
public class BrandsRepository {
public static final String TAG = "BrandsRepository";
MutableLiveData<List<Brand>> mutableLiveData;
Retrofit retrofit;
@Inject
public BrandsRepository(Retrofit retrofit) {
this.retrofit = retrofit;
}
public LiveData<List<Brand>> getListOfBrands() {
// Retrofit retrofit = ApiManager.getAdapter();
final BrandsService brandsService = retrofit.create(BrandsService.class);
Log.d(TAG, "getListOfBrands: 00000000000 "+retrofit);
mutableLiveData = new MutableLiveData<>();
Call<List<Brand>> retrofitCall = brandsService.getBrands();
retrofitCall.enqueue(new Callback<List<Brand>>() {
@Override
public void onResponse(Call<List<Brand>> call, Response<List<Brand>> response) {
mutableLiveData.setValue(response.body());
}
@Override
public void onFailure(Call<List<Brand>> call, Throwable t) {
t.printStackTrace();
}
});
return mutableLiveData;
}
}
我正在通过注入(inject) Retrofit 来使用 Dagger2 的构造函数注入(inject)。 然后我有一个像这样的 ViewModel
public class BrandsViewModel extends ViewModel{
BrandsRepository brandsRepository;
LiveData<List<Brand>> brandsLiveData;
@Inject
public BrandsViewModel(BrandsRepository brandsRepository) {
this.brandsRepository = brandsRepository;
}
public void callService(){
brandsLiveData = brandsRepository.getListOfBrands();
}
public LiveData<List<Brand>> getBrandsLiveData() {
return brandsLiveData;
}
}
要在 BrandsRepository 中注入(inject) Retrofit,我必须像那样注入(inject) BrandsRepository。 然后我有这样的 MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Inject
BrandsViewModel brandsViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((MainApplication)getApplication()).getNetComponent().inject(this);
// BrandsViewModel brandsViewModel = ViewModelProviders.of(this).get(BrandsViewModel.class);
brandsViewModel.callService();
LiveData<List<Brand>> brandsLiveData = brandsViewModel.getBrandsLiveData();
brandsLiveData.observe(this, new Observer<List<Brand>>() {
@Override
public void onChanged(@Nullable List<Brand> brands) {
Log.d(TAG, "onCreate: "+brands.get(0).getName());
}
});
}
}
BrandsViewModel 是使用 Dagger2 而不是 ViewModelProviders 注入(inject)的。这工作正常但是当我尝试通过取消注释来使用 ViewModelProviders 时,dagger 给我一个明显的错误。获取 ViewModel 的正确方法是使用 ViewModelProviders,但我将如何在注入(inject)这样的改造时实现这一点。
最佳答案
编辑:重要说明。要使用 Jetpack ViewModel,您不需要 map-multibinding。继续阅读。
答案可能比 Mumi 的方法更简单,即在组件上公开 ViewModel:
@Singleton
@Component(modules={...})
public interface SingletonComponent {
BrandsViewModel brandsViewModel();
}
现在您可以在 ViewModelFactory 中的组件上访问此方法:
// @Inject
BrandsViewModel brandsViewModel;
...
brandsViewModel = new ViewModelProvider(this, new ViewModelProvider.Factory() {
@Override
public <T extends ViewModel> create(Class<T> modelClazz) {
if(modelClazz == BrandsViewModel.class) {
return singletonComponent.brandsViewModel();
}
throw new IllegalArgumentException("Unexpected class: [" + modelClazz + "]");
}).get(BrandsViewModel.class);
所有这些都可以使用 Kotlin 进行简化和隐藏:
inline fun <reified T: ViewModel> AppCompatActivity.createViewModel(crossinline factory: () -> T): T = T::class.java.let { clazz ->
ViewModelProvider(this, object: ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if(modelClass == clazz) {
@Suppress("UNCHECKED_CAST")
return factory() as T
}
throw IllegalArgumentException("Unexpected argument: $modelClass")
}
}).get(clazz)
}
现在可以让你做
brandsViewModel = createViewModel { singletonComponent.brandsViewModel() }
现在在哪里BrandsViewModel可以从 Dagger 接收它的参数:
class BrandsViewModel @Inject constructor(
private val appContext: Context,
/* other deps */
): ViewModel() {
...
}
尽管如果 Provider<BrandsViewModel> 的 Intent 可能更清晰而是从 Dagger 暴露
interface SingletonComponent {
fun brandsViewModel(): Provider<BrandsViewModel>
}
brandsViewModel = createViewModel { singletonComponent.brandsViewModel().get() }
来自 android-ktx 的一些额外技巧, 你甚至可以做
@Suppress("UNCHECKED_CAST")
inline fun <reified T : ViewModel> Fragment.fragmentViewModels(
crossinline creator: () -> T
): Lazy<T> {
return createViewModelLazy(T::class, storeProducer = {
viewModelStore
}, factoryProducer = {
object : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(
modelClass: Class<T>
): T = creator.invoke() as T
}
})
}
然后
class ProfileFragment: Fragment(R.layout.profile_fragment) {
private val viewModel by fragmentViewModels {
singletonComponent.brandsViewModelFactory().get()
}
在哪里brandsViewModelFactory()是
fun brandsViewModelFactory(): Provider<BrandsViewModel>
关于android - 带有 Dagger 2 的 ViewModelProviders,无法掌握概念,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50673266/
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e
我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳
我在pry中定义了一个函数:to_s,但我无法调用它。这个方法去哪里了,怎么调用?pry(main)>defto_spry(main)*'hello'pry(main)*endpry(main)>to_s=>"main"我的ruby版本是2.1.2看了一些答案和搜索后,我认为我得到了正确的答案:这个方法用在什么地方?在irb或pry中定义方法时,会转到Object.instance_methods[1]pry(main)>defto_s[1]pry(main)*'hello'[1]pry(main)*end=>:to_s[2]pry(main)>defhello[2]pry(main)
我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类
当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub
GivenIamadumbprogrammerandIamusingrspecandIamusingsporkandIwanttodebug...mmm...let'ssaaay,aspecforPhone.那么,我应该把“require'ruby-debug'”行放在哪里,以便在phone_spec.rb的特定点停止处理?(我所要求的只是一个大而粗的箭头,即使是一个有挑战性的程序员也能看到:-3)我已经尝试了很多位置,除非我没有正确测试它们,否则会发生一些奇怪的事情:在spec_helper.rb中的以下位置:require'rubygems'require'spork'
我正在学习http://ruby.railstutorial.org/chapters/static-pages上的RubyonRails教程并遇到以下错误StaticPagesHomepageshouldhavethecontent'SampleApp'Failure/Error:page.shouldhave_content('SampleApp')Capybara::ElementNotFound:Unabletofindxpath"/html"#(eval):2:in`text'#./spec/requests/static_pages_spec.rb:7:in`(root)'