Android dataBinding-无法通知更改视图 [英] Android dataBinding - unable to notify view of changes
问题描述
我正试图出于目的使用数据绑定。我创建了一个项目,该项目将启动倒数计时器。如果时间是质数,则应以xml布局更新TextView。计时器工作正常,但textview从未更新。
i am trying to use databinding for a purpose. I have a project i've created that starts a countdown timer. If the time is a prime number it should update a TextView in a xml layout. The timer works fine but the textview never gets updated.
这是我的计时器,可以正常工作:
here is my timer which works fine:
public class MyCountDownTimer {
private CountDownTimer countDownTimer;
private boolean isExecuting =false;
private ICountDownListener listener;
private final String TAG = getClass().getSimpleName();
public MyCountDownTimer(ICountDownListener listener){
this.listener = listener;
}
public void startTimer(long timeLeftMillis) {
if (!isExecuting) {
isExecuting = true;
countDownTimer = new CountDownTimer(timeLeftMillis, 1000) {
@Override
public void onTick(long millisUntilFinished) {
;
if(isPrime(millisUntilFinished/1000)){
listener.doSomethingWithPrimeCountDown(millisUntilFinished / 1000);
}
}
@Override
public void onFinish() {
isExecuting = false;
listener.doSomethingWithPrimeCountDown(0L);
}
};
countDownTimer.start();
} else {
Log.i(TAG, "Timer already started");
}
} m
public void cancelTimer() {
if (isExecuting) {
countDownTimer.cancel();
isExecuting = false;
}
}
public void restartTimer(Long milli) {
cancelTimer();
startTimer(milli);
}
//checks whether an int is prime or not.
boolean isPrime(Long n) {
//check if n is a multiple of 2
if (n%2==0) return false;
//if not, then just check the odds
for(int i=3;i*i<=n;i+=2) {
if(n%i==0)
return false;
}
return true;
}
}
我有一个用于将计时器滴答声发送给正在收听的人的接口:
I have a interface that is used to send the timer ticks out to whoever is listening:
public interface ICountDownListener {
void doSomethingWithPrimeCountDown(Long count);
}
和主要的Activity类我实际绑定到数据的地方看起来像这样:
and the main Activity class where i actually bind to the data looks like this:
public class MainActivity extends FragmentActivity {
CountdownBinder mCountdownBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
mCountdownBinder = DataBindingUtil.setContentView(this, R.layout.activity_main);
//Lets reference our textview just for fun
mCountdownBinder.tvGreen.setText("initial text");
ViewModel vModel = ViewModel.instance();
//now tell databinding about your viewModel below
mCountdownBinder.setViewModel(viewModel);
vModel.startCounting(200000L); //start a countdown
}
}
,这是我创建的ViewModel的非常重要的部分。它是一个单例类,它扩展了BaseObservable并实现了ICountDownListener,以便可以侦听刻度线:
and here is the very important part the ViewModel i created. Its a singleton class and it extends BaseObservable and implements ICountDownListener so it can listen for ticks:
package com.databindingexample.mycompany.databindingexample.ViewModels;
import android.databinding.BaseObservable;
import android.databinding.Bindable;
import android.databinding.BindingAdapter;
import android.graphics.Color;
import android.util.Log;
import android.widget.TextView;
import com.databindingexample.mycompany.databindingexample.Interfaces.ICountDownListener;
import com.databindingexample.mycompany.databindingexample.MyCountDownTimer;
//notice we are subclassing BaseObservable
public class ViewModel extends BaseObservable implements ICountDownListener{
private static ViewModel instance;
private long countDownTime;
private MyCountDownTimer mCountDownTimer;
//lock the constructor as this is a singleton
private ViewModel(){
mCountDownTimer=new MyCountDownTimer(this);
}
public static ViewModel instance() {
if (instance == null) {
instance = new ViewModel();
}
return instance;
}
@Bindable
public long getCountDownTime() {
return countDownTime;
}
public void setCountDownTime(long countDownTime) {
this.countDownTime = countDownTime;
//this seems to not notify the UI, nothings changing
notifyPropertyChanged((int) countDownTime);
//this log prints out
Log.d("TAG","prime tick:"+countDownTime);
}
@BindingAdapter({"app:primeColor"})
public static void setTextColor(TextView view, String color) {
if("green".equals(color))
view.setTextColor(Color.parseColor("#63f421"));
else if("pink".equals(color))
view.setTextColor(Color.parseColor("#ffc0cb"));
}
public void startCounting(Long milli){
mCountDownTimer.restartTimer(milli);
}
@Override
public void doSomethingWithPrimeCountDown(Long count) {
setCountDownTime(count);
}
}
注意:app:primeColor属性bindableAdapter可以正常工作只是可绑定的getCountdownTime()那是行不通的。
note: the app:primeColor attribute bindableAdapter works fine its just the bindable getCountdownTime() thats not working.
这是xml文件:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data class="CountdownBinder">
<variable name="viewModel" type="com.databindingexample.mycompany.databindingexample.ViewModels.ViewModel"/>
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.databindingexample.mycompany.databindingexample.MainActivity"
tools:showIn="@layout/activity_main">
<TextView
android:id="@+id/tv_green"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:primeColor='@{"pink"}'
android:text="@{Long.toString(viewModel.getCountDownTime)}" />
</RelativeLayout>
</layout>
更新:
感谢SO的出色回答,我写了一个在dataBinding上发布博客以帮助他人。
推荐答案
更新绑定当然需要某种通知。
Updating the binding requires of course some kind of notifying.
这是notifyPropertyChanged出现的地方。
每个@Bindable带注释的属性都会在BR类中生成一个ID(您可以根据需要更改此行为)。
This is where notifyPropertyChanged comes in. Every @Bindable Annotated Property will generate a id in the BR class (you can change this behaviour if you really want).
所以您不会通过调用notifyPropertyChanged(BR.fieldName)来触发变量本身。
So you are not firing the variable itself by calling notifyPropertyChanged(BR.fieldName) .
请查看 http://developer.android.com/tools/data-binding/guide.html 或更高版本,请检查
Take a look at the docs at http://developer.android.com/tools/data-binding/guide.html or better, check the generated code to get a understanding how the 'magic' works.
一个可观察对象应该(或者可以,因为您可以完全独立于分配值来触发属性更改通知) :
A observable Object should (or can, since you can fire property change notifications completly independent from assigning a value):
public class User extends BaseObservable {
private String firstName;
private String lastName;
@Bindable
public String getFirstName() {
return this.firstName;
}
@Bindable
public String getLastName() {
return this.lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
notifyPropertyChanged(BR.firstName);
}
public void setLastName(String lastName) {
this.lastName = lastName;
notifyPropertyChanged(BR.lastName);
}
}
这篇关于Android dataBinding-无法通知更改视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!