Android ViewModel 对象使用 kotlin 重新创建,但不使用 java
Android ViewModel object recreate with kotlin but not with java
我是 kotlin 和 mvvm 的新手,但我能够使它在 java 中工作,但是当我在 kotlin 中创建一个新示例 mvvm-retrofit-corutines 时,视图模型被调用所有调用 OnCreate 函数的时间(根据文档不应该发生,并且在 java 中工作正常)。
主要活动:
lateinit var viewModel : MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//Here we can see the logs in every orientation changed in the emulator.
viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
viewModel.getMutableLiveDataModel().observe(this, Observer {
Log.d("zzzz","lamda executes onChanged method -> "+ it.otherValues). //element from model
})
}
我的视图模型:
class MyViewModel : ViewModel() {
private lateinit var objectTypeModel: MutableLiveData<MyTestModel>
fun getMutableLiveDataModel():MutableLiveData<MyTestModel>{
//Gets the model from a retrofit service call
objectTypeModel = MyRepository.getModelFromService()
return objectTypeModel
}
}
我是不是做错了什么?已经尝试按照其他 post.
中的建议将 'viewModel' 转换为局部变量
Java Code, MainActivity
MyViewModel model;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
model = new ViewModelProvider(this).get(MyViewModel.class);
model.getUsers().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer users) {
Log.d("zzzz","updated value..")
}
});
}
Model
public class MyViewModel extends ViewModel {
private MutableLiveData<Integer> users;
public LiveData<Integer> getUsers() {
if (users == null) {
users = new MutableLiveData<Integer>();
users.setValue(10);
}
return users;
}
}
如果您不想重新创建视图模型,请像这样声明您的视图模型
private val model: MyViewModel by activityViewModels()
有关详细信息,请参阅 ViewModel
我认为问题出在你的 kotlin viewmodel class,如果你没有得到价值(除非你在其他 classes 中有更多问题)
修复你的kotlin viewmodel class 其中数据没有设置在MutableLiveData,你忘了添加一段代码。
//Here it is like this
objectTypeModel.value= MyRepository.getModelFromService()
AFAIK onCreate() 仅在创建 activity 时被调用。因此,如果您的视图模型再次被创建,这是很自然的。您还可以在视图模型 class.
中通过 init{}
方法检查它
不过,如果您不满意,请将您的 api 调用从 activity 的 onCreate()
方法移动到 viewmodels init{}
方法并观察从 Activity 变化而来。您的 getMutableLiveDataModel()
将在创建视图模型对象时调用一次。
如果您的 java 视图模型示例如您所料 运行ning。然后,尝试将 java class 转换为 kotlin 并再次 运行 (只需将 java 代码粘贴到 kotlin 文件中,它会要求您转换它),它应该工作。
尝试
MainActivity
lateinit var viewModel : MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
viewModel.objectTypeModel.observe(this, Observer {
Log.d("zzzz","lamda executes onChanged method -> "+ it.otherValues).
//element from model
})
}
ViewModel
class MyViewModel : ViewModel() {
val objectTypeModel= MutableLiveData<MyTestModel>()
init {
objectTypeModel.value = MyRepository.getModelFromService()
}
}
我尝试了相同的概念,正如预期的那样,Java 和 Kotlin 中的功能是相同的。在 LogCat 中,我希望日志应该在每次轮换时打印出来,确实如此。现在,让我告诉你为什么会这样。
因此,根据文档 ViewModel
实例在配置更改后保持活动状态。基本上,如果您的 activity 多次重新创建但它没有被破坏(调用 finish()
),ViewModel
使用相同的实例。但这不是 ViewModel
的魔力,而是 LiveData
.
的魔力
LiveData
是一个可观察的数据视图持有者,因此它会在您在 onCreate()
.
中观察到的每个配置更改时将最新的保留值发送给活动观察者
让我向您展示我的代码。
Java
// Activity
public class JavaActivity extends AppCompatActivity {
private static final String TAG = "JavaActivity";
private JavaViewModel javaViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_java);
// Ignore this listener
findViewById(R.id.go_to_kotlin_activity).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
// Main
javaViewModel = new ViewModelProvider(this).get(JavaViewModel.class);
javaViewModel.getJavaLiveData().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
Log.d(TAG, "onChanged: " + integer);
}
});
}
}
// ViewModel
public class JavaViewModel extends ViewModel {
private MutableLiveData<Integer> javaLiveData;
public LiveData<Integer> getJavaLiveData() {
if(javaLiveData == null) {
javaLiveData = new MutableLiveData<>();
javaLiveData.setValue(10);
}
return javaLiveData;
}
}
Kotlin
// Activity
class KotlinActivity : AppCompatActivity() {
companion object {
private const val TAG = "KotlinActivity"
}
private lateinit var kotlinViewModel: KotlinViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_kotlin)
// Ignore this listener
findViewById<Button>(R.id.go_to_java_activity_btn).setOnClickListener {
startActivity(Intent(this, JavaActivity::class.java))
}
// Main
kotlinViewModel = ViewModelProvider(this).get(KotlinViewModel::class.java)
kotlinViewModel.getKotlinLiveData().observe(this, Observer {
Log.d(TAG, "onCreate: $it")
})
}
}
// ViewModel
class KotlinViewModel : ViewModel() {
private lateinit var kotlinLiveData: MutableLiveData<Int>
fun getKotlinLiveData(): LiveData<Int> {
if (!::kotlinLiveData.isInitialized) {
kotlinLiveData = MutableLiveData()
kotlinLiveData.value = 10
}
return kotlinLiveData
}
}
如果您有任何后续问题,请在评论中留下。
谢谢!
参考资料
我是 kotlin 和 mvvm 的新手,但我能够使它在 java 中工作,但是当我在 kotlin 中创建一个新示例 mvvm-retrofit-corutines 时,视图模型被调用所有调用 OnCreate 函数的时间(根据文档不应该发生,并且在 java 中工作正常)。
主要活动:
lateinit var viewModel : MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//Here we can see the logs in every orientation changed in the emulator.
viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
viewModel.getMutableLiveDataModel().observe(this, Observer {
Log.d("zzzz","lamda executes onChanged method -> "+ it.otherValues). //element from model
})
}
我的视图模型:
class MyViewModel : ViewModel() {
private lateinit var objectTypeModel: MutableLiveData<MyTestModel>
fun getMutableLiveDataModel():MutableLiveData<MyTestModel>{
//Gets the model from a retrofit service call
objectTypeModel = MyRepository.getModelFromService()
return objectTypeModel
}
}
我是不是做错了什么?已经尝试按照其他 post.
中的建议将 'viewModel' 转换为局部变量Java Code, MainActivity
MyViewModel model;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
model = new ViewModelProvider(this).get(MyViewModel.class);
model.getUsers().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer users) {
Log.d("zzzz","updated value..")
}
});
}
Model
public class MyViewModel extends ViewModel {
private MutableLiveData<Integer> users;
public LiveData<Integer> getUsers() {
if (users == null) {
users = new MutableLiveData<Integer>();
users.setValue(10);
}
return users;
}
}
如果您不想重新创建视图模型,请像这样声明您的视图模型
private val model: MyViewModel by activityViewModels()
有关详细信息,请参阅 ViewModel
我认为问题出在你的 kotlin viewmodel class,如果你没有得到价值(除非你在其他 classes 中有更多问题)
修复你的kotlin viewmodel class 其中数据没有设置在MutableLiveData,你忘了添加一段代码。
//Here it is like this objectTypeModel.value= MyRepository.getModelFromService()
AFAIK onCreate() 仅在创建 activity 时被调用。因此,如果您的视图模型再次被创建,这是很自然的。您还可以在视图模型 class.
中通过init{}
方法检查它不过,如果您不满意,请将您的 api 调用从 activity 的
onCreate()
方法移动到 viewmodelsinit{}
方法并观察从 Activity 变化而来。您的getMutableLiveDataModel()
将在创建视图模型对象时调用一次。如果您的 java 视图模型示例如您所料 运行ning。然后,尝试将 java class 转换为 kotlin 并再次 运行 (只需将 java 代码粘贴到 kotlin 文件中,它会要求您转换它),它应该工作。
尝试
MainActivity
lateinit var viewModel : MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
viewModel.objectTypeModel.observe(this, Observer {
Log.d("zzzz","lamda executes onChanged method -> "+ it.otherValues).
//element from model
})
}
ViewModel
class MyViewModel : ViewModel() {
val objectTypeModel= MutableLiveData<MyTestModel>()
init {
objectTypeModel.value = MyRepository.getModelFromService()
}
}
我尝试了相同的概念,正如预期的那样,Java 和 Kotlin 中的功能是相同的。在 LogCat 中,我希望日志应该在每次轮换时打印出来,确实如此。现在,让我告诉你为什么会这样。
因此,根据文档 ViewModel
实例在配置更改后保持活动状态。基本上,如果您的 activity 多次重新创建但它没有被破坏(调用 finish()
),ViewModel
使用相同的实例。但这不是 ViewModel
的魔力,而是 LiveData
.
LiveData
是一个可观察的数据视图持有者,因此它会在您在 onCreate()
.
让我向您展示我的代码。
Java
// Activity
public class JavaActivity extends AppCompatActivity {
private static final String TAG = "JavaActivity";
private JavaViewModel javaViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_java);
// Ignore this listener
findViewById(R.id.go_to_kotlin_activity).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
// Main
javaViewModel = new ViewModelProvider(this).get(JavaViewModel.class);
javaViewModel.getJavaLiveData().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
Log.d(TAG, "onChanged: " + integer);
}
});
}
}
// ViewModel
public class JavaViewModel extends ViewModel {
private MutableLiveData<Integer> javaLiveData;
public LiveData<Integer> getJavaLiveData() {
if(javaLiveData == null) {
javaLiveData = new MutableLiveData<>();
javaLiveData.setValue(10);
}
return javaLiveData;
}
}
Kotlin
// Activity
class KotlinActivity : AppCompatActivity() {
companion object {
private const val TAG = "KotlinActivity"
}
private lateinit var kotlinViewModel: KotlinViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_kotlin)
// Ignore this listener
findViewById<Button>(R.id.go_to_java_activity_btn).setOnClickListener {
startActivity(Intent(this, JavaActivity::class.java))
}
// Main
kotlinViewModel = ViewModelProvider(this).get(KotlinViewModel::class.java)
kotlinViewModel.getKotlinLiveData().observe(this, Observer {
Log.d(TAG, "onCreate: $it")
})
}
}
// ViewModel
class KotlinViewModel : ViewModel() {
private lateinit var kotlinLiveData: MutableLiveData<Int>
fun getKotlinLiveData(): LiveData<Int> {
if (!::kotlinLiveData.isInitialized) {
kotlinLiveData = MutableLiveData()
kotlinLiveData.value = 10
}
return kotlinLiveData
}
}
如果您有任何后续问题,请在评论中留下。 谢谢!
参考资料