从视图模型类获取活动的上下文

gam*_*ofe 7 android mvvm android-recyclerview android-databinding android-viewmodel

我基于发现使用Android体系结构组件和数据绑定的示例创建了代码。对我而言,这是一种新方法,并且对其进行编码的方式使得很难正确地使用单击的帖子的信息来打开新活动。

这是帖子的适配器

class PostListAdapter : RecyclerView.Adapter<PostListAdapter.ViewHolder>() {
    private lateinit var posts: List<Post>

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PostListAdapter.ViewHolder {
        val binding: ItemPostBinding = DataBindingUtil.inflate(
            LayoutInflater.from(parent.context),
            R.layout.item_post,
            parent, false
        )

        return ViewHolder(binding)
    }

    override fun onBindViewHolder(holder: PostListAdapter.ViewHolder, position: Int) {
        holder.bind(posts[position])
    }

    override fun getItemCount(): Int {
        return if (::posts.isInitialized) posts.size else 0
    }

    fun updatePostList(posts: List<Post>) {
        this.posts = posts
        notifyDataSetChanged()
    }

    inner class ViewHolder(private val binding: ItemPostBinding) : RecyclerView.ViewHolder(binding.root) {
        private val viewModel = PostViewModel()

        fun bind(post: Post) {
            viewModel.bind(post)
            binding.viewModel = viewModel
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

bind方法来自视图模型类内:

class PostViewModel : BaseViewModel() {
    private val image = MutableLiveData<String>()
    private val title = MutableLiveData<String>()
    private val body = MutableLiveData<String>()

    fun bind(post: Post) {
        image.value = post.image
        title.value = post.title
        body.value = post.body
    }

    fun getImage(): MutableLiveData<String> {
        return image
    }

    fun getTitle(): MutableLiveData<String> {
        return title
    }

    fun getBody(): MutableLiveData<String> {
        return body
    }

    fun onClickPost() {
        // Initialize new activity from here, perhaps?
    }
}
Run Code Online (Sandbox Code Playgroud)

在布局XML中,设置onClick属性

android:onClick =“ @ {()-> viewModel.onClickPost()}”

指向此onClickPost方法确实可以,但是我不能Intent从那里初始化。我尝试了很多方法来获取MainActivitiy的上下文,但都没有成功,例如

val intent = Intent(MainActivity :: getApplicationContext,PostDetailActivity :: class.java)

但是它会按时显示错误。

Jac*_*key 3

尝试:android:onClick="@{(view) -> viewModel.onClickPost(view)}"

还要更改onClickPost以获取视图。然后,您可以使用view.getContext()视图上的方法来访问存储在该视图中的上下文。

但是,由于 ViewModel 不应引用视图或任何其他保存 Activity 上下文的类,因此将启动 Activity 的逻辑放在 ViewModel 中是非常不合适的。您绝对应该考虑一个单独的地方来这样做。

就我个人而言,对于我的代码,如果它是一个简单的 startActivity ,没有任何额外的包袱,我会创建一个单独的类来保存静态方法。通过数据绑定,我将导入该类并在 onClick 中使用它,以使用上面所说的方法启动一个新的 Activity。

一个例子:

public class ActivityHandler{        
    public static void showNextActivity(View view, ViewModel viewModel){
        Intent intent = new Intent(); //Create your intent and add extras if needed
        view.getContext().startActivity(intent);
    }
}

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <import type="whatever.you.want.ActivityHandler" />
        <variable name="viewmodel" type="whatever.you.want.here.too.ViewModel" />
    </data>

    <Button
        //Regular layout properties
        android:onClick="@{(view) -> ActivityHandler.showNextActivity(view, viewmodel)}"
        />
</layout>
Run Code Online (Sandbox Code Playgroud)

在这里查看侦听器绑定:https://developer.android.com/topic/libraries/data-binding/expressions#listener_bindings

但是,根据所需的数据量,您可能希望将 startActivity 代码放置在最适合您的应用程序设计的其他类中。