Вы можете использовать .equals
для столбцов или целых фреймов данных.
df['col1'].equals(df['col2'])
Если они равны, этот оператор вернет True
, else False
.
Первая ошибка довольно явная: binding.viewModel ожидает обнуляемый UserListViewModel? и получить необнуляемый UserListViewModel (см. kotlin null safety doc ). Вы можете попробовать что-то вроде этого, чтобы избавиться от него:
Объявите вашу viewModel как
private var viewModel: UserListViewModel? = null
и установите привязку следующим образом:
viewModel?.let{binding.viewModel = it}
Относительно второго ошибка, ваши объявления выглядят нормально, но иногда кэш Android Studio повреждается, попробуйте Invalidate Caches / Restart, это может помочь.
Несоответствие типов. Требуется: MyUser.UserListViewModel? Найдено: com.example. ***. Ui.MyUser.UserListViewModel
В основном ошибка говорит о том, что ваш
binding.viewModel //is a nullable type and there for it expects a nullable
//type to be assigned as well
Так что просто превратите вашу модель представления в обнуляемый тип, добавив ? символ после его делакариона (обратите внимание, что поздние типы инициализации не допускают обнуляемые типы). попробуйте вот так
private var viewModel: UserListViewModel? = null
Что касается библиотеки ошибок связывания второй ошибки, которую нужно скомпилировать, чтобы автоматически сгенерировать класс привязки, просто пересоберите проект, и эта ошибка исчезнет.
Пожалуйста, не стесняйтесь использовать этот шаблон в качестве основы, чтобы избежать всего этого стандартного кода
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS)
annotation class ContentView(@LayoutRes val id: Int)
fun ViewGroup.inflate(@LayoutRes layoutId: Int,
addContainer: Boolean = false): View {
return LayoutInflater.from(context).inflate(layoutId,this,addContainer)
}
@Suppress("UNCHECKED_CAST")
abstract class BaseFragment<Model : ViewModel, Binding : ViewDataBinding> : Fragment() {
/**
* Data binding class variable all view elements declared on the
* Xml file will be available within this instance if a view model
* Is required for the xml to work we will need to bind it on @onBindViewModel
*/
protected lateinit var binding: WeakReference<Binding?>
/**
* Fragments view model according to MVVM android architecture
* Each fragment class should have one , in order to facilitate
* Live Data and Binding library features, tho we can skip it
*/
protected lateinit var viewModel: WeakReference<Model?>
/**
* Here is where most likely you will get not null data , both binding and
* view model references can be destroyed by garbage collector
* If this application reaches low memory levels
*
* This optional method is used to bind the required view model inside the
* Xml file, this is optional to use tho is recommended
* Bind them by calling the view model binding.customViewModel = viewModel
*/
protected open fun onBindViewModel(viewModel: Model?, binding: Binding?) {}
/**
* There will be the occasion where custom params will be needed on view model's
* Constructor in this case will want to override the default creation @see ViewModelFactory
*/
protected open fun onCreateViewModel(modelType: Class<Model>): Model? = if (modelType != ViewModel::class.java)
ViewModelProviders.of(requireActivity()).get(modelType) else null
/**
* Here we will inherit view model and binding values based on the class
* Parameters and store them in global variables so any class extending
* From Base activity has access to binding and view model instances by default
*/
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val layout = this.javaClass.annotations.find { it.annotationClass == ContentView::class } as ContentView?
?: throw RuntimeException("You annotate this class with @ContentView and provide a layout resource")
container?.let { binding = WeakReference(DataBindingUtil.bind(it.inflate(layout.id))!!) }
?: run { binding = WeakReference(DataBindingUtil.bind(inflater.inflate(layout.id, null))) }
viewModel = WeakReference(
onCreateViewModel(
(this.javaClass.genericSuperclass
as ParameterizedType).actualTypeArguments[0] as Class<Model>
)
)
setHasOptionsMenu(true)
onBindViewModel(viewModel.get(), binding.get())
return binding.get()?.root
}
}
И просто используйте его вот так (посмотрите, сколько кода на плите пропало)
@ContentView(R.layout.fragment_user)
class UserFragment: BaseFragment<UserListViewModel, FragmentUserBinding> {
override fun onBindViewModel(viewModel: UserListViewModel?, binding: FragmentUserBinding?) {
binding.viewModel = viewModel
}
}