Nano Hash - криптовалюты, майнинг, программирование

Как использовать привязку данных Android для привязки интерфейса?

у меня есть ситуация, когда у меня есть фрагмент, чьи текстовые поля будут заполнены либо X1Object, либо X2Object, которые оба реализуют интерфейс IXObject и расширяют класс BaseObservable, предоставляемый библиотекой Android DataBinding, но содержат дополнительные различные поля и поведение. IXObject содержит методы для геттеров и сеттеров.

public interface IXObject {
    void setName(String name);
    String getName();
}

public class X1Object extends BaseObservable implements IXObject {
    private String name;

    @Override
    @Bindable
    public String getName() {
        return name;
    }

    @Override
    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }
}

public class X2Object extends BaseObservable implements IXObject {...}

Затем я пытаюсь использовать один файл макета для фрагмента, используя Android DataBinding. Макет выглядит следующим образом:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>
    <variable name="xObject" type="com.test.x.model.IXObject"/>
</data>

<LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@{xObject.name}"/>

</LinearLayout>
</layout>

В классе фрагментов я применяю привязку:

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    MyFragmentBinding binding = DataBindingUtil.inflate(inflater, R.layout.my_fragment, container, false);

    View view = binding.getRoot();

    IXObject xobj = new X1Object();
    binding.setXObject(xobject);

    return view;
}

К сожалению, при использовании IXObject в качестве ссылки на привязку данных метод addOnPropertyChangedCallback в классе BaseObservable никогда не вызывается.

Используя X1Object напрямую для привязки в файле макета и классе привязки, все работает отлично.

Можете ли вы помочь мне, как достичь моей цели, чтобы использовать интерфейс для привязки?

Спасибо.

01.06.2017

Ответы:


1

Я также не могу найти способ заставить его работать с интерфейсом, но я думаю, что вы можете использовать абстрактный класс следующим образом.

public abstract class IXObject extends BaseObservable {
    public abstract void setName(String name);

    @Bindable
    public abstract String getName();
}

.

public class X1Object extends IXObject {
    private String name;

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }
}

.

final IXObject xobj = new X1Object();
xobj.setName("nguyen");
binding.setXObject(xobj);
01.06.2017
  • на случай, если вы совершите ту же ошибку, что и я, и метод get должен следовать соглашению JavaBeans — получателю нужен префикс get 19.09.2019

  • 2

    Когда вы объявляете переменную в файле макета, вы должны воспринимать ее буквально. интерфейсы не являются объектами. Я знаю, что Java поддерживает общие встроенные объекты, где вы можете объявить интерфейс, как если бы он был объектом, но в целом они не являются объектами.

    Поэтому, когда вы говорите файлу макета использовать переменную типа интерфейса, он действительно мало что может сделать, поскольку не является объектом.

    Одна вещь, которую вы заметите и ненавидите в привязке данных Android, заключается в том, что она не может выводить типы. Поэтому, если вы пытаетесь установить переменную с помощью реализующего класса, но надеетесь сделать это с помощью интерфейса, вам не повезет.

    Вам нужно указать класс, который будет использоваться, а не интерфейс, от которого эти классы наследуются. Как указывалось в другом ответе, вы можете использовать базовый класс, если ваш базовый класс имеет необходимые методы.

    Также быстрое замечание: вы можете просто поместить привязку к частной переменной-члену, и она все равно будет автоматически проходить через геттер и сеттер.

    Единственное, что вы можете сделать, это создать адаптер, который берет интерфейс, или ваш интерфейс, или даже Any с приведением, и устанавливает имя для вас. Для этого требуется еще один адаптер в вашем уже растущем классе адаптеров, но, по крайней мере, их легко сделать.

    03.08.2018

    3

    Я думаю, что нашел корень своей проблемы. Согласно документации по привязке данных, каждая переменная, установленная в макете, должна реализовывать интерфейс Observable:

    Типы переменных проверяются во время компиляции, поэтому, если переменная реализует Observable или является наблюдаемой коллекцией, это должно быть отражено в типе. Если переменная является базовым классом или интерфейсом, который не реализует интерфейс Observable*, переменные не будут наблюдаться!

    Так что возможности использовать интерфейс не будет. Я должен использовать абстрактный класс, как указано в ответе выше.

    01.06.2017

    4

    Просто используйте @get:Bindable вместо @Bindable внутри своего интерфейса. Вместо этого используйте LiveData: https://developer.android.com/topic/libraries/data-binding/architecture

    18.12.2019
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..