@ Санлок Ли Ок. Как насчет добавления условия в функцию, чтобы предотвратить инициализацию, когда она не нужна. Проверьте мой отредактированный ответ.

ли способ передать дополнительный аргумент в мой обычайAndroidViewModel конструктор кроме контекста приложения. Пример:

public class MyViewModel extends AndroidViewModel {
    private final LiveData<List<MyObject>> myObjectList;
    private AppDatabase appDatabase;

    public MyViewModel(Application application, String param) {
        super(application);
        appDatabase = AppDatabase.getDatabase(this.getApplication());

        myObjectList = appDatabase.myOjectModel().getMyObjectByParam(param);
    }
}

И когда я хочу использовать свой пользовательскийViewModel класс я использую этот код в моем фрагменте:

MyViewModel myViewModel = ViewModelProvider.of(this).get(MyViewModel.class)

Так что я не знаю, как передать дополнительный аргументString param в мой обычайViewModel, Я могу только передать контекст приложения, но не дополнительные аргументы. Я был бы очень признателен за любую помощь. Спасибо.

Изменить: я добавил немного кода. Я надеюсь, что теперь лучше.

 hugo18 сент. 2017 г., 19:25
добавить больше деталей и код
 Mario Rudman18 сент. 2017 г., 23:25
Там нет сообщения об ошибке. Я просто не знаю, где установить аргументы для конструктора, так как ViewModelProvider используется для создания объектов AndroidViewModel.
 Moses Aprico18 сент. 2017 г., 22:42
Что за сообщение об ошибке?

Ответы на вопрос(5)

которая должна сделать эту задачу более простой и понятной, не требуя многократных привязок или заводских шаблонов, одновременно работая с аргументами ViewModel, которые могут быть предоставлены Dagger как зависимости:https://github.com/radutopor/ViewModelFactory

@ViewModelFactory
class UserViewModel(@Provided repository: Repository, userId: Int) : ViewModel() {

    val greeting = MutableLiveData<String>()

    init {
        val user = repository.getUser(userId)
        greeting.value = "Hello, $user.name"
    }    
}

По мнению:

class UserActivity : AppCompatActivity() {
    @Inject
    lateinit var userViewModelFactory2: UserViewModelFactory2

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_user)
        appComponent.inject(this)

        val userId = intent.getIntExtra("USER_ID", -1)
        val viewModel = ViewModelProviders.of(this, userViewModelFactory2.create(userId))
            .get(UserViewModel::class.java)

        viewModel.greeting.observe(this, Observer { greetingText ->
            greetingTextView.text = greetingText
        })
    }
}

Допустим, вы не хотите создавать один и тот же класс Factory каждый раз, когда создаете новый класс ViewModel, для которого нужны аргументы. Вы можете сделать это с помощью Reflection.

Например, у вас будет два разных вида деятельности:

class Activity1 : FragmentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val args = Bundle().apply { putString("NAME_KEY", "Vilpe89") }
        val viewModel = ViewModelProviders.of(this, ViewModelWithArgumentsFactory(args))
            .get(ViewModel1::class.java)
    }
}

class Activity2 : FragmentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val args = Bundle().apply { putInt("AGE_KEY", 29) }
        val viewModel = ViewModelProviders.of(this, ViewModelWithArgumentsFactory(args))
            .get(ViewModel2::class.java)
    }
}

И ViewModels для этих видов деятельности:

class ViewModel1(private val args: Bundle) : ViewModel()

class ViewModel2(private val args: Bundle) : ViewModel()

Тогда волшебная часть, реализация класса Factory:

class ViewModelWithArgumentsFactory(private val args: Bundle) : NewInstanceFactory() {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        try {
            val constructor: Constructor<T> = modelClass.getDeclaredConstructor(Bundle::class.java)
            return constructor.newInstance(args)
        } catch (e: Exception) {
            Timber.e(e, "Could not create new instance of class %s", modelClass.canonicalName)
            throw e
        }
    }
}
Решение Вопроса

У вас должен быть фабричный класс для вашей ViewModel.

public class MyViewModelFactory implements ViewModelProvider.Factory {
    private Application mApplication;
    private String mParam;


    public MyViewModelFactory(Application application, String param) {
        mApplication = application;
        mParam = param;
    }


    @Override
    public <T extends ViewModel> T create(Class<T> modelClass) {
        return (T) new MyViewModel(mApplication, mParam);
    }
}

И при создании экземпляра модели представления вы делаете так:

MyViewModel myViewModel = ViewModelProviders.of(this, new MyViewModelFactory(this.getApplication(), "my awesome param")).get(MyViewModel.class);
 jackycflau21 нояб. 2018 г., 07:52
как насчет использованияreturn modelClass.cast(new MyViewModel(mApplication, mParam)) избавиться от предупреждения
 Tim02 авг. 2018 г., 19:57
Ваша ViewModel будет воссоздана после изменения ориентации. Ваш не может создать фабрику каждый раз.
 dmlebron17 мар. 2018 г., 19:18
но каждыйViewModel может / будет иметь другой DI. Как бы вы узнали, какой экземпляр вернуть наcreate() метод?
 dmlebron16 мар. 2018 г., 16:12
Делает каждыйViewModel классу нужен его ViewModelFactory?
 mlyko03 авг. 2018 г., 11:05
Это не правда. новыйViewModel создание предотвращает методget(), На основе документации: «Возвращает существующую ViewModel или создает новую в области (обычно фрагмент или действие), связанную с этим ViewModelProvider». видеть:developer.android.com/reference/android/arch/lifecycle/...

совместно используемой несколькими моделями представлений, я бы расширил ответ mlyko следующим образом:

public class MyViewModelFactory extends ViewModelProvider.NewInstanceFactory {
    private Application mApplication;
    private Object[] mParams;

    public MyViewModelFactory(Application application, Object... params) {
        mApplication = application;
        mParams = params;
    }

    @Override
    public <T extends ViewModel> T create(Class<T> modelClass) {
        if (modelClass == ViewModel1.class) {
            return (T) new ViewModel1(mApplication, (String) mParams[0]);
        } else if (modelClass == ViewModel2.class) {
            return (T) new ViewModel2(mApplication, (Integer) mParams[0]);
        } else if (modelClass == ViewModel3.class) {
            return (T) new ViewModel3(mApplication, (Integer) mParams[0], (String) mParams[1]);
        } else {
            return super.create(modelClass);
        }
    }
}

И инстанцирующий вид моделей:

ViewModel1 vm1 = ViewModelProviders.of(this, new MyViewModelFactory(getApplication(), "something")).get(ViewModel1.class);
ViewModel2 vm2 = ViewModelProviders.of(this, new MyViewModelFactory(getApplication(), 123)).get(ViewModel2.class);
ViewModel3 vm3 = ViewModelProviders.of(this, new MyViewModelFactory(getApplication(), 123, "something")).get(ViewModel3.class);

С разным видом модели, имеющие разные конструкторы.

 rzehan12 июн. 2018 г., 12:24
@mlyko Конечно, это все действительные возражения, и всегда есть собственный метод (ы) для настройки данных модели представления. Но иногда вы хотите убедиться, что viewmodel был инициализирован, следовательно, используется конструктор. В противном случае вы сами должны обработать ситуацию "viewmodel еще не инициализирован". Например, если viewmodel имеет методы, которые возвращают LivedData, и наблюдатели присоединяются к этому в различных методах жизненного цикла View.
 mlyko17 мая 2018 г., 19:56
Я не рекомендую этот способ, потому что есть несколько причин: 1) параметры на фабрике не являются безопасными по типу - таким образом, вы можете нарушить ваш код во время выполнения. Всегда старайтесь избегать этого подхода, когда это возможно. 2) Проверка типов моделей представлений не является ООП-способом. Так как ViewModels преобразуются в базовый тип, снова вы можете нарушать код во время выполнения без каких-либо предупреждений во время компиляции. В этом случае я бы предложил использовать фабрику Android по умолчанию и передать параметры в уже созданную модель представления.

public class MyViewModel extends AndroidViewModel {
    private final LiveData<List<MyObject>> myObjectList;
    private AppDatabase appDatabase;
    private boolean initialized = false;

    public MyViewModel(Application application) {
        super(application);
    }

    public initialize(String param){
      synchronized ("justInCase") {
         if(! initialized){
          initialized = true;
          appDatabase = AppDatabase.getDatabase(this.getApplication());
          myObjectList = appDatabase.myOjectModel().getMyObjectByParam(param);
    }
   }
  }
}

а затем использовать его в два этапа:

MyViewModel myViewModel = ViewModelProvider.of(this).get(MyViewModel.class)
myViewModel.initialize(param)
 Amr Berag05 мар. 2019 г., 05:37
@ Санлок Ли Ок. Как насчет добавления условия в функцию, чтобы предотвратить инициализацию, когда она не нужна. Проверьте мой отредактированный ответ.
 Sanlok Lee04 мар. 2019 г., 22:45
Весь смысл помещения параметров в конструктор состоит в том, чтобы инициализировать только модель представления.один раз, С вашей реализацией, если вы позвонитеmyViewModel.initialize(param) вonCreate например, его можно вызывать несколько раз на одном и том жеMyViewModel экземпляр, как пользователь поворачивает устройство.

Ваш ответ на вопрос