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 中有更多问题)

  1. 修复你的kotlin viewmodel class 其中数据没有设置在MutableLiveData,你忘了添加一段代码。

     //Here it is like this
     objectTypeModel.value= MyRepository.getModelFromService()
    
  2. AFAIK onCreate() 仅在创建 activity 时被调用。因此,如果您的视图模型再次被创建,这是很自然的。您还可以在视图模型 class.

    中通过 init{} 方法检查它
  3. 不过,如果您不满意,请将您的 api 调用从 activity 的 onCreate() 方法移动到 viewmodels init{} 方法并观察从 Activity 变化而来。您的 getMutableLiveDataModel() 将在创建视图模型对象时调用一次。

  4. 如果您的 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()

    }
}

我尝试了相同的概念,正如预期的那样,JavaKotlin 中的功能是相同的。在 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
    }
}

如果您有任何后续问题,请在评论中留下。 谢谢!

参考资料