Android-привязка данных к котлину с ошибками фрагментов: невозможно найти импорт символа com.example. ***. Databinding.FragmentUserBindingImpl;

Вы можете использовать .equals для столбцов или целых фреймов данных.

df['col1'].equals(df['col2'])

Если они равны, этот оператор вернет True, else False.

0
задан user3770803 27 March 2019 в 06:34
поделиться

2 ответа

Первая ошибка довольно явная: binding.viewModel ожидает обнуляемый UserListViewModel? и получить необнуляемый UserListViewModel (см. kotlin null safety doc ). Вы можете попробовать что-то вроде этого, чтобы избавиться от него:

Объявите вашу viewModel как

private var viewModel: UserListViewModel? = null

и установите привязку следующим образом:

viewModel?.let{binding.viewModel = it}

Относительно второго ошибка, ваши объявления выглядят нормально, но иногда кэш Android Studio повреждается, попробуйте Invalidate Caches / Restart, это может помочь.

0
ответ дан Robert LaFondue 27 March 2019 в 06:34
поделиться

Несоответствие типов. Требуется: 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
}
}
0
ответ дан Juan Hurtado 27 March 2019 в 06:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: