如何克服实现字符串资源数据绑定的问题



我在数据绑定方面遇到了问题。我正在尝试包含一个XML布局,用于设置所包含TextViewtag。但是,它解析为以布局为前缀并以 _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);
}

我已经查看并基于如何使用数据绑定将资源中的字符串与 XML 中的动态变量组合?

我已通读数据绑定库

我已经打开了数据绑定并将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'
}

经过相当多的尝试,我似乎找到了解决方案,那就是使用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 - Android 中的数据绑定发现了这一点。相关摘录是:-

数据绑定活动

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

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

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

使用数据绑定时,将从布局自动生成 Binding 类 文件。默认情况下,该类使用布局文件名命名。这 默认名称是通过将每个字母的首字母大写来生成的 下划线后的单词,删除所有下划线,然后添加 "绑定"到名称。因此,activity_main.xml将导致 类名为 ActivityMainBinding。 若要在代码中关联此自动生成的绑定类,请 invoke DataBindingUtil's 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);
}
});

在上面的代码片段中,您会注意到我们可以访问 直接更新按钮按钮。数据中包含"@+id"的所有视图 绑定布局会自动分配给 正确的类型。所以按钮更新按钮是为布局按钮创建的 使用 '@+id/updateButton',并为 id/text_view1 文本视图。

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

最新更新