可能的this副本
我正在使用dagger2探索android注入api。因此,在示例应用程序中,我直接在活动中注入了var map;
var myLatLng;
$(document).ready(function() {
geoLocationInit();
function geoLocationInit() {
if (navigator.geolocation) {
navigator.geoLocation.getCurrentPosition(success, fail);
} else {
alert("Browser not supported");
}
}
function success(position) {
console.log(position);
var Latval = position.coords.latitude;
var Lngval = position.coords.longitude;
myLatLng = new google.maps.LatLng(Latval, Lngval);
createMap(myLatLng);
}
function fail() {
alert("It Failed");
}
//Create Map
function createMap(myLatLng) {
var myLatLng = new google.maps.LatLng(0.3285284, 32.5738946);
map = new google.maps.Map(document.getElementById('map'), {
center: myLatLng,
zoom: 12
});
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
});
}
//Create marker
function createMarker(LatLng, icn, name) {
var marker = new google.maps.Marker({
position: LatLng,
map: map,
icon: icn,
title: name
});
}
//Nearby search
function nearbySearch(myLatLng, type) {
var request = {
location: myLatLng,
radius: '1500',
types: [type]
};
service = new google.maps.places.PlacesService(map);
service.nearbySearch(request, callback);
function callback(results, status) {
//console.log(results);
if (status == google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
var place = results[i];
LatLng = place.geometry.location;
icn = place.icon;
name = place.name;
createMarker(LatLng, icn, name);
}
}
}
}
});
;看看下面的代码片段。
ViewModel
class SampleApp : Application(), HasActivityInjector {
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>
override fun activityInjector(): AndroidInjector<Activity> =
dispatchingAndroidInjector
override fun onCreate() {
super.onCreate()
DaggerApplicationComponent.builder()
.application(this)
.build()
.inject(this)
}
}
@Component(modules = [
AndroidInjectionModule::class,
ActivityBindingModule::class,
AppModule::class
/** Other modules **/
])
@Singleton
interface ApplicationComponent {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): ApplicationComponent
}
fun inject(sampleApp: SampleApp)
}
@Module
public abstract class ActivityBindingModule {
@ContributesAndroidInjector(modules = MainModule.class)
public abstract MainActivity contributeMainActivityInjector();
}
class MainActivity : AppCompatActivity() {
@Inject
lateinit var mainViewModel: mainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_dashboard)
}
}
如您所见,我已经将@Module
public class MainModule {
@Provides
public static MainViewModelProviderFactory provideMainViewModelProviderFactory(/** some dependencies **/) {
return new MainViewModelProviderFactory(/** some dependencies **/);
}
@Provides
public static MainViewModel provideMainViewModel(MainActivity activity, MainViewModelProviderFactory factory) {
return ViewModelProviders.of(activity, factory).get(MainViewModel.class);
}
}
直接注入了活动。现在,如果我轮换活动,则注入的实例将有所不同。
但是,如果我将MainViewModel
注入MainViewModelProviderFactory
中并执行
MainActivity
返回与以前相同的实例。
我没有发现我的实现有什么问题。
任何指针都是有意义的。
答案 0 :(得分:7)
因此,在检查了ViewModelProvider
,ViewModelProviders
,FragmentActivity
和是dagger2 documentation
的来源之后,我有了答案。
如果我错了,请随时纠正我。.
我们绝对不能直接注入 ViewModel ,我们应该注入工厂。
由于AndroidInjection.inject(this)
这行,我正面临这个问题。
根据匕首作者
在Activity中的super.onCreate()之前调用AndroidInjection.inject()至关重要
让我们从高层次看这里出了什么问题。
活动将使用onRetainNonConfigurationInstance
保留其ViewModel
的旋转状态,并将其恢复到onCreate()
由于我们在调用super.onCreate()
之前进行注入,因此不会获得保留的MainViewModel
对象,而是获得新的对象。
如果需要详细信息,请继续阅读。
当匕首尝试注入MainViewModel
时,它将调用provideMainViewModel()
的{{1}}方法,该方法将调用以下表达式(请注意,MainModule
尚未被调用)
super.onCreate()
ViewModelProviders.of(activity, factory).get(MainViewModel.class)
将返回一个ViewModelProviders.of
,其中包含相应活动的ViewModelProvider
和ViewModelStore
ViewModelProviderFactory
public static ViewModelProvider of(@NonNull FragmentActivity activity,
@Nullable Factory factory) {
.
.
return new ViewModelProvider(ViewModelStores.of(activity), factory);
}
最终将调用活动ViewModelStore.of(activity)
,因为在这种情况下,活动为getViewModelStore()
,它实现了AppCompatActivity
ViewModelStoreOwner
如果为空,则创建新的AppCompatActivity
并保留对其的引用。 ViewModelStore
是ViewModelStore
的包装,并带有其他方法Map<String, ViewModel>
clear()
只要设备旋转,活动就会使用onRetainNonConfigurationInstance
保留其非配置实例状态,并在@NonNull
public ViewModelStore getViewModelStore() {
if (this.getApplication() == null) {
throw new IllegalStateException("Your activity is not yet attached to the Application instance. You can't request ViewModel before onCreate call.");
} else {
if (this.mViewModelStore == null) {
this.mViewModelStore = new ViewModelStore();
}
return this.mViewModelStore;
}
}
中将其恢复。
onCreate
将尝试从活动的ViewModelProvider.get
中获取ViewModel
ViewModelStore
在此特定示例中;因为我们还没有调用public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
//noinspection unchecked
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
viewModel = mFactory.create(modelClass);
mViewModelStore.put(key, viewModel);
//noinspection unchecked
return (T) viewModel;
}
方法,实现会要求super.onCreate()
创建它并更新相应的factory
。
因此,我们最终有了两个不同的ViewModelStore
对象。