首页 > 解决方案 > 使用数据绑定将viewmodel绑定到recyclerview item.xml,android?

问题描述

我想从 xml 布局文件中的 viewmodel 绑定适配器上的数据

这是我的片段类。

class NotificationFragment : Fragment() {
var customeProgressDialog: CustomeProgressDialog? = null
private val appPreferences: AppPreference by inject()
private val notificationViewModel: NotificationViewModel by viewModel()
private lateinit var binding: FragmentNotificationBinding

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    binding = FragmentNotificationBinding.inflate(inflater, container, false)
    return binding.getRoot()
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    binding.notification.layoutManager=LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
    customeProgressDialog = CustomeProgressDialog(activity)
    notificationViewModel.notifications(
        appPreferences.getUsername(),
        appPreferences.getPassword(),
        appPreferences.getUserId()
    )
    initObservables()
}

private fun initObservables() {
    notificationViewModel.progressDialog?.observe(this, Observer {
        if (it!!) customeProgressDialog?.show() else customeProgressDialog?.dismiss()
    })
    notificationViewModel.apiResponse?.observe(
        viewLifecycleOwner,
        androidx.lifecycle.Observer { response ->
            if (response.dataList != null) {
                var notificationAdapter = NotificationAdapter(response.dataList as List<Data>)
                notificationAdapter.notifyDataSetChanged()
                binding.notification.adapter = notificationAdapter
            }
        })
}
}

我的视图模型

class NotificationViewModel(networkCall: NetworkCall) : ViewModel(),
Callback<ApiResponse> {
var progressDialog: SingleLiveEvent<Boolean>? = null
var apiResponse: MutableLiveData<ApiResponse>? = null
var networkCall: NetworkCall;
init {
    progressDialog = SingleLiveEvent<Boolean>()
    apiResponse = MutableLiveData<ApiResponse>()
    this.networkCall = networkCall
}

fun notifications(username: String?, password: String?, userId: String?) {
    progressDialog?.value = true
    val apiPost = ApiPost()
    apiPost.userName = username
    apiPost.password = password
    apiPost.UserId = userId
    apiPost.FileType = NetworkConstant.FILE_TYPE_NOT
    networkCall.getPDF(apiPost).enqueue(this)
}

override fun onFailure(call: Call<ApiResponse>, t: Throwable) {
    progressDialog?.value = false
}

override fun onResponse(call: Call<ApiResponse>, response: Response<ApiResponse>) {
    progressDialog?.value = false
    apiResponse?.value = response.body()
}
}

适配器类

lass NotificationAdapter(private val list: List<Data>) :
RecyclerView.Adapter<NotificationAdapter.ViewHolder>() {


override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val inflater = LayoutInflater.from(parent.context)
    val view = inflater.inflate(R.layout.element_list, parent, false)
    return ViewHolder(view)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val movie: Data = list[position]
    holder.bind(movie)
    holder.itemView.setOnClickListener {

        if (!TextUtils.isEmpty(movie.filePath)) {
            try {
                val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(movie.filePath))
                holder.itemView.context.startActivity(browserIntent)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

    }
}

override fun getItemCount(): Int = list.size

inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    fun bind(movie: Data) {
        with(itemView) {
            tv_notifi.text = movie.displayName
            tv_date.text = movie.UpdatedDate
            if (movie.description != null) {
                tv_brief.text = movie.description
                tv_brief.visibility = View.VISIBLE
            }
        }
    }
}

}

这是我的项目 xml 布局

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<data>
    <variable
        name="viewmodel"
        type="com.mountmeru.viewmodel.NotificationViewModel" />
</data>

<androidx.cardview.widget.CardView
    android:id="@+id/main_cardview"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="5dp">

    <androidx.appcompat.widget.LinearLayoutCompat
        android:id="@+id/main_cardrl"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <RelativeLayout
            android:id="@+id/rl_newsdate"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="0.3">

            <androidx.appcompat.widget.AppCompatTextView
                android:id="@+id/tv_notifi"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:layout_marginTop="10dp"
                android:layout_marginRight="10dp"
                android:maxLines="2"
                android:text="hey i am notification text"
                android:textColor="@android:color/black"
                android:textSize="16sp" />

            <androidx.appcompat.widget.AppCompatTextView
                android:id="@+id/tv_brief"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/tv_notifi"
                android:layout_marginLeft="10dp"
                android:layout_marginTop="5dp"
                android:layout_marginRight="10dp"
                android:textColor="@android:color/black"
                android:textSize="16sp"
                android:visibility="gone" />

            <androidx.appcompat.widget.AppCompatTextView
                android:id="@+id/tv_date"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/tv_brief"
                android:layout_marginLeft="10dp"
                android:layout_marginTop="2dp"
                android:layout_marginRight="10dp"
                android:maxLines="1"
                android:text="hey i am date"
                android:textColor="@color/inactive_text"
                android:textSize="14sp" />
        </RelativeLayout>

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_toRightOf="@+id/rl_newsdate"
            android:layout_weight="0.7"
            android:padding="5dp">

            <androidx.appcompat.widget.AppCompatImageView
                android:id="@+id/iv_notifi"
                android:layout_width="match_parent"
                android:layout_height="75dp"
                android:layout_centerHorizontal="true"
                android:layout_centerVertical="true"
                android:src="@drawable/mer" />

        </RelativeLayout>

    </androidx.appcompat.widget.LinearLayoutCompat>

</androidx.cardview.widget.CardView>
</layout>

我能够为片段进行绑定,但对于适配器我不确定如何继续。

标签: androidkotlinandroid-recyclerviewdata-bindingviewmodel

解决方案


If I understand your question correctly, you want to pass data to your adapter inside xml. For this, you will need to write custom binding adapter for your RecyclerView. This link has all you need. https://android.jlelse.eu/how-to-bind-a-list-of-items-to-a-recyclerview-with-android-data-binding-1bd08b4796b4


推荐阅读