【问题标题】:How to overcome issues with implementing String Resource DataBinding如何克服实现字符串资源数据绑定的问题
【发布时间】:2017-07-02 11:12:49
【问题描述】:

我遇到了数据绑定问题。我正在尝试包含一个 XML 布局,设置包含的 TextViewtag。但是,它会解析为包含布局的名称以 layout 为前缀并以 _0 为后缀,即layout/common_helpinfo_0

在我的主要布局中:-

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <LinearLayout
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:orientation="vertical"
        ....
        <LinearLayout
            .....
            >
            <TextView
                .... />
            <include layout="@layout/common_helpinfo"
                android:id="@+id/hi_tag_world1"
                app:tagstr="@{@string/hi_tag_world1}"
                >
            </include>
        </LinearLayout>
        ....
    </LinearLayout>
</layout>

包含的布局common_helpinfo 是:-

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable name="tagstr" type="String"/>
    </data>
    <TextView
        ....
        android:tag="@{tagstr}"
        ''''
        android:onClick="clickHelpInfo"
        >
    </TextView>
</layout>

为了测试这一点,我的MainActivity 中有以下内容:-

     public void clickHelpInfo(View v) {
        String hicaller = v.getTag().toString();
        int vid = v.getId();

        Toast.makeText(this,"You Clicked Help from button=" + hicaller + " ID+" + Integer.toString(vid)
                , Toast.LENGTH_SHORT).show();
    }

在我的主布局中,包含的 TextView 的硬编码等效项:-

        <TextView
            ....
            android:tag="@string/hi_tag_world1"
            ''''
            android:onClick="clickHelpInfo"
            >
        </TextView>

这按预期工作,Toast 显示字符串资源 hi_tag_world1 的内容。

ActivitMainBinding 中,编译成功后,我有以下内容,似乎显示了错误数据的设置位置(请注意,我实际上包含了 common_helpinfo两次都表现相同):-

private static final android.util.SparseIntArray sViewsWithIds;
static {
    sIncludes = new android.databinding.ViewDataBinding.IncludedLayouts(12);
    sIncludes.setIncludes(1, 
        new String[] {"common_helpinfo"}, <<<<<
        new int[] {3},
        new int[] {R.layout.common_helpinfo}); <<<<<
    sIncludes.setIncludes(2, 
        new String[] {"common_helpinfo"}, <<<<<
        new int[] {4},
        new int[] {R.layout.common_helpinfo}); <<<<<
    sViewsWithIds = new android.util.SparseIntArray();
    sViewsWithIds.put(R.id.vtext01, 5);
    sViewsWithIds.put(R.id.vtext02, 6);
    sViewsWithIds.put(R.id.vtext03, 7);
    sViewsWithIds.put(R.id.tvhi03, 8);
    sViewsWithIds.put(R.id.etext01, 9);
    sViewsWithIds.put(R.id.actvemail, 10);
    sViewsWithIds.put(R.id.lvemail, 11);
}

但后来在 ActivityMainBinding 我得到以下似乎试图获取正确数据:-

@Override
protected void executeBindings() {
    long dirtyFlags = 0;
    synchronized(this) {
        dirtyFlags = mDirtyFlags;
        mDirtyFlags = 0;
    }
    // batch finished
    if ((dirtyFlags & 0x4L) != 0) {
        // api target 1

        this.hiTagWorld1.setTagstr(getRoot().getResources().getString(R.string.hi_tag_world1));
        this.hiTagWorld2.setTagstr(getRoot().getResources().getString(R.string.hi_tag_world2));
    }
    executeBindingsOn(hiTagWorld1);
    executeBindingsOn(hiTagWorld2);
}

我查看了我的代码并将其基于How do I use databinding to combine a string from resources with a dynamic variable in XML?

我已经阅读了Data Binding Library

我已打开 DataBinding 并将 build.gradle 设置为:-

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "mjt.testvcsuse"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    dataBinding {
        enabled = true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.1.0'
    testCompile 'junit:junit:4.12'
}

【问题讨论】:

    标签: android-xml android-resources android-databinding


    【解决方案1】:

    玩了一阵子之后,我似乎找到了一个解决方案,那就是使用dataBindingUtilsetContentView 方法替换setContentView 方法。

    例如final ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);

    即而不是:-

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ....
        }
    

    绑定使用:-

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            final ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
            ....
        }
    

    我通过阅读这篇由 Obaro Ogbo 撰写的文章 Android Authority - Data Binding in Android 发现了这一点。相关的摘录是:-

    数据绑定活动

    目前,我们有一个支持数据绑定的布局文件。 但是,为了利用它的数据绑定能力,我们必须将它加载到一个 不同的方式。

    以前,您会像这样加载布局:

    setContentView(R.layout.activity_main);
    final Button button1 = (Button)findViewById(R.id.button1);
    button.setOnClickListener(...);
    

    使用数据绑定,绑定类会从您的布局中自动生成 文件。默认情况下,该类使用您的布局文件名命名。这 默认名称是通过每个首字母大写生成的 下划线后的单词,删除所有下划线,然后添加 “绑定”到名称。因此,activity_main.xml 将导致 名为 ActivityMainBinding 的类。 要在您的代码中关联这个自动生成的绑定类,您 调用 DataBindingUtil 的 setContentView

    final ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(
        this, R.layout.activity_main);
    activityMainBinding.updateButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            activityMainBinding.textView1.setText(R.string.text1b);
        }
    });
    

    在上面的代码 sn-p 中,你会注意到我们可以访问 updateButton 按钮直接。数据中带有“@+id”的所有视图 绑定布局会自动分配给 正确的类型。所以 Button updateButton 是为布局 Button 创建的 使用“@+id/updateButton”,并为 id/text_view1 文本视图。

    它似乎不会干扰现有视图,例如非数据绑定/硬编码的 TextView onClick 处理在没有其他代码更改的情况下仍然有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-20
      • 2011-08-24
      • 1970-01-01
      相关资源
      最近更新 更多