blob: f64365b6d00777f5c95be52ddfe04171a4344658 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.arch.lifecycle;
import android.annotation.SuppressLint;
import android.app.Application;
import android.arch.lifecycle.ViewModelProvider.Factory;
import android.support.annotation.MainThread;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import java.lang.reflect.InvocationTargetException;
/**
* Utilities methods for {@link ViewModelStore} class.
*/
public class ViewModelProviders {
@SuppressLint("StaticFieldLeak")
private static DefaultFactory sDefaultFactory;
private static void initializeFactoryIfNeeded(Application application) {
if (sDefaultFactory == null) {
sDefaultFactory = new DefaultFactory(application);
}
}
/**
* Creates a {@link ViewModelProvider}, which retains ViewModels while a scope of given
* {@code fragment} is alive. More detailed explanation is in {@link ViewModel}.
* <p>
* It uses {@link DefaultFactory} to instantiate new ViewModels.
*
* @param fragment a fragment, in whose scope ViewModels should be retained
* @return a ViewModelProvider instance
*/
@MainThread
public static ViewModelProvider of(@NonNull Fragment fragment) {
FragmentActivity activity = fragment.getActivity();
if (activity == null) {
throw new IllegalArgumentException(
"Can't create ViewModelProvider for detached fragment");
}
initializeFactoryIfNeeded(activity.getApplication());
return new ViewModelProvider(ViewModelStores.of(fragment), sDefaultFactory);
}
/**
* Creates a {@link ViewModelProvider}, which retains ViewModels while a scope of given Activity
* is alive. More detailed explanation is in {@link ViewModel}.
* <p>
* It uses {@link DefaultFactory} to instantiate new ViewModels.
*
* @param activity an activity, in whose scope ViewModels should be retained
* @return a ViewModelProvider instance
*/
@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity) {
initializeFactoryIfNeeded(activity.getApplication());
return new ViewModelProvider(ViewModelStores.of(activity), sDefaultFactory);
}
/**
* Creates a {@link ViewModelProvider}, which retains ViewModels while a scope of given
* {@code fragment} is alive. More detailed explanation is in {@link ViewModel}.
* <p>
* It uses the given {@link Factory} to instantiate new ViewModels.
*
* @param fragment a fragment, in whose scope ViewModels should be retained
* @param factory a {@code Factory} to instantiate new ViewModels
* @return a ViewModelProvider instance
*/
@MainThread
public static ViewModelProvider of(@NonNull Fragment fragment, @NonNull Factory factory) {
return new ViewModelProvider(ViewModelStores.of(fragment), factory);
}
/**
* Creates a {@link ViewModelProvider}, which retains ViewModels while a scope of given Activity
* is alive. More detailed explanation is in {@link ViewModel}.
* <p>
* It uses the given {@link Factory} to instantiate new ViewModels.
*
* @param activity an activity, in whose scope ViewModels should be retained
* @param factory a {@code Factory} to instantiate new ViewModels
* @return a ViewModelProvider instance
*/
@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity,
@NonNull Factory factory) {
return new ViewModelProvider(ViewModelStores.of(activity), factory);
}
/**
* {@link Factory} which may create {@link AndroidViewModel} and
* {@link ViewModel}, which have an empty constructor.
*/
@SuppressWarnings("WeakerAccess")
public static class DefaultFactory extends ViewModelProvider.NewInstanceFactory {
private Application mApplication;
/**
* Creates a {@code DefaultFactory}
*
* @param application an application to pass in {@link AndroidViewModel}
*/
public DefaultFactory(@NonNull Application application) {
mApplication = application;
}
@Override
public <T extends ViewModel> T create(Class<T> modelClass) {
if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
//noinspection TryWithIdenticalCatches
try {
return modelClass.getConstructor(Application.class).newInstance(mApplication);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (InstantiationException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (InvocationTargetException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
}
}
return super.create(modelClass);
}
}
}