Привязка данных Android не работает при использовании inflate() класса привязки

Я новичок в привязке данных. У меня есть файл макета, как показано ниже:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable name="userProfile" type="com.demo.entity.UserProfile"/>
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="16dp">
        <TextView
            android:id="@+id/username_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:textSize="20sp"
            android:textStyle="bold"
            android:text="@{userProfile.username}" />
    </RelativeLayout>
</layout>

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

Следовательно, мой код выглядит так:

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    inflateActivityViewInFrame(R.layout.activity_profile, R.string.action_profile);
    initialiseData();
}

private void initialiseData() {
    ActivityProfileBinding binding = ActivityProfileBinding.inflate(getLayoutInflater());
    UserProfile userProfile = new UserProfile("Croaking Tiger Riding Dragon", 8, 16, 32);
    binding.setUserProfile(userProfile);
}

Метод inflateActivityViewInFrame() в родительском классе делает только это:

protected void inflateActivityViewInFrame(int layoutId, int titleStringId) {
    LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(layoutId, mFrameLayout, false);
    mFrameLayout.addView(view);

    setupActionBarAndDrawerToggle(titleStringId);
}

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

public class UserProfile {
    private final String username;
    private final int numContributions;
    private final int numBookmarks;
    private final int numLikes;

    public UserProfile(String username, int numContributions, int numLikes, int numBookmarks) {
        this.username = username;
        this.numContributions = numContributions;
        this.numBookmarks = numBookmarks;
        this.numLikes = numLikes;
    }

Есть мысли, почему это не работает?


person AA_PV    schedule 03.11.2016    source источник
comment
потому что ваше поле закрыто   -  person Beloo    schedule 03.11.2016
comment
@Beloo У всех полей есть общедоступные геттеры ... извините, я не прикрепил этот код, чтобы он был кратким, но это похоже на то, что я упомянул в вопросе :)   -  person AA_PV    schedule 03.11.2016
comment
Просто добавьте, что макет также хорош тем, что он отображается, когда используется постоянная строка вместо связанных данных в android:text.   -  person AA_PV    schedule 03.11.2016


Ответы (1)


Проблема в том, что вы раздуваете макет в inflateActivityViewInFrame, а затем снова раздуваете его (без прикрепления) в initialiseData. Вы можете сделать то или другое. Либо это:

protected <T extends ViewDataBinding> T inflateActivityViewInFrame(
        int layoutId, int titleStringId) {
  LayoutInflater inflater = (LayoutInflater)
      getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  T binding = DataBindingUtil.inflate(inflater, layoutId, mFrameLayout, true);
  setupActionBarAndDrawerToggle(titleStringId);
}

а затем используйте return ViewDataBinding для установки данных:

ActivityProfileBinding binding = 
    inflateActivityViewInFrame(R.layout.activity_profile, R.string.action_profile); 
UserProfile userProfile = new UserProfile("Croaking Tiger Riding Dragon", 8, 16, 32);
binding.setUserProfile(userProfile);

Или вы можете просто привязать уже раздутый макет.

protected View inflateActivityViewInFrame(int layoutId, int titleStringId) {
    LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(layoutId, mFrameLayout, false);
    mFrameLayout.addView(view);

    setupActionBarAndDrawerToggle(titleStringId);
    return view;
}

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    View view = inflateActivityViewInFrame(
        R.layout.activity_profile, R.string.action_profile);
    initialiseData(view);
}

private void initialiseData(View view) {
    ActivityProfileBinding binding = ActivityProfileBinding.bind(view);
    UserProfile userProfile = new UserProfile("Croaking Tiger Riding Dragon", 8, 16, 32);
    binding.setUserProfile(userProfile);
}

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

person George Mount    schedule 03.11.2016
comment
Большое спасибо за это, из руководства разработчика я не знал, что весь этот API существует! - person AA_PV; 04.11.2016