GVKun编程网logo

android.databinding.ObservableBoolean的实例源码(android data obb)

25

如果您对android.databinding.ObservableBoolean的实例源码和androiddataobb感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解android.data

如果您对android.databinding.ObservableBoolean的实例源码android data obb感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解android.databinding.ObservableBoolean的实例源码的各种细节,并对android data obb进行深入的分析,此外还有关于android -------- Data Binding 的使用(三)Observable、Android Data Binding 系列 (二) -- Binding 与 Observer 实现原理、Android Studio 4.0.1:构建失败:不建议使用“ android.databinding.enableV2”选项、android – Observable返回类型必须参数化为Observable或Observable的实用技巧。

本文目录一览:

android.databinding.ObservableBoolean的实例源码(android data obb)

android.databinding.ObservableBoolean的实例源码(android data obb)

项目:Cinder    文件:CinderBooleanUnitTest.java   
@Test
public void takeTakesCorrectTimes() throws Exception {
    String string1 = "STRING 1";
    String string2 = "STRING 2";
    ObservableField<String> observed = new ObservableField<>(string1);
    ObservableBoolean observing = Cinder.computeBoolean(()->
        observed.get().equals(string1),observed).take(2).immediate();
    assertTrue(observing.get());

    observed.set(string2);
    assertFalse(observing.get());

    observed.set(string1);
    assertFalse(observing.get());
}
项目:Cinder    文件:CinderBooleanUnitTest.java   
@Test
public void skipSkipsCorrectTimes() throws Exception {
    String string1 = "STRING 1";
    String string2 = "STRING 2";
    ObservableField<String> observed = new ObservableField<>(string1);
    ObservableBoolean observing = Cinder.computeBoolean(()->
        observed.get().equals(string1),observed).skip(1);

    observed.set(string1);
    assertFalse(observing.get());

    observed.set(string2);
    assertFalse(observing.get());

    observed.set(string1);
    assertTrue(observing.get());
}
项目:devfest-2016-realm    文件:PasswordReadviewmodel.java   
public PasswordReadviewmodel(Navigator navigator,PasswordInteractor interactor,int id) {
  this.navigator = navigator;
  this.interactor = interactor;
  this.id = id;

  this.title = new ObservableField<>();
  this.icon = new ObservableField<>();
  this.username = new ObservableField<>();
  this.password = new ObservableField<>();
  this.displayPassword = new ObservableBoolean(false);
  this.customFields = new ObservableArrayList<>();

  realmPassword = interactor.readPassword(id);
  realmPassword.addchangelistener(this::updateView);

  updateView(realmPassword);
}
项目:rx-property-android    文件:RxCommand.java   
/**
 * Creates {@code RxCommand} to execute the specified command from the specified {@link
 * Observable} with the specified initial state.
 *
 * @param canExecuteSource an {@link Observable} to emit whether this {@code RxCommand} can
 *                         execute
 * @param canExecute       whether this {@code RxCommand} can execute initially
 */
public RxCommand(@Nullable final Observable<Boolean> canExecuteSource,boolean canExecute) {
    canExecuteFlag = new ObservableBoolean(canExecute);

    if (canExecuteSource != null) {
        canExecuteSourcedisposable = canExecuteSource.distinctUntilChanged()
                .subscribeWith(new disposableObserver<Boolean>() {
                    @Override
                    public void onNext(Boolean value) {
                        canExecuteFlag.set(value);
                    }

                    @Override
                    public void onError(Throwable e) {
                        kicker.onError(e);
                        RxCommand.this.dispose();
                    }

                    @Override
                    public void onComplete() {
                        kicker.onComplete();
                        RxCommand.this.dispose();
                    }
                });
    }
}
项目:Anago    文件:SignInActivityviewmodel.java   
@Inject
public SignInActivityviewmodel(BaseActivity activity,SignInUseCase signInUseCase,CheckSessionUseCase checkSessionUseCase) {
    super(activity);

    this.signInUseCase = signInUseCase;
    this.checkSessionUseCase = checkSessionUseCase;

    name = new ObservableField<>();
    password = new ObservableField<>();
    buttonEnabled = new ObservableBoolean(false);

    checkSessionUseCase.run()
            .compose(bindToLifecycle().forSingle())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(authToken -> {
                Timber.v("Check session: " + authToken.token);
                Toast.makeText(getContext(),"Already signed in",Toast.LENGTH_SHORT).show();
                goToNext();
            },Timber::e);
}
项目:RxDataBinding    文件:ObservableBooleanObservable.java   
Listener(final ObservableBoolean observableBoolean,final Observer<? super Boolean> observer) {
  this.observableBoolean = observableBoolean;
  this.onPropertyChangedCallback =
      new android.databinding.Observable.OnPropertyChangedCallback() {
        @Override
        public void onPropertyChanged(android.databinding.Observable observable,int ignoredPropertyId) {
          if (!isdisposed()) {
            ObservableBoolean observableBoolean = (ObservableBoolean) observable;
            observer.onNext(observableBoolean.get());
          }
        }
      };
}
项目:Twitter_Client    文件:Followersviewmodel.java   
public Followersviewmodel(@NonNull DataListener dataListener,@NonNull Context context,TwitterSession session,Long userId) {
    this.dataListener = dataListener;
    this.context = context;
    this.session = session;
    this.userId = userId;
    activityFollowerProgressBar = new ObservableInt(View.VISIBLE);
    activityFollowerSwipeRefreshLayout = new ObservableInt(View.GONE);
    activityFollowerRecyclerView = new ObservableInt(View.GONE);
    activityFollowerIsPullToRefresh = new ObservableBoolean(false);
    initializeViews();
    fetchFollowersList(false,false,cursor);
}
项目:SimpleFTP    文件:Explorerviewmodel.java   
/**
 * Default constructor.
 * @param context The context of the current activity.
 */
public Explorerviewmodel(Context context) {
    this.context = context;
    this.isLoading = new ObservableBoolean(false);
    this.isRefreshing = new ObservableBoolean(false);
    this.files = new ObservableArrayList<Fileviewmodel>();
    this.isSelectionMode = new ObservableBoolean(false);
    this.numberSelectedItems = new ObservableInt(0);
    this.changeDirectory("/");
}
项目:SimpleFTP    文件:ListServerviewmodel.java   
/**
 * Default constructor.
 * @param context The context of the current activity.
 */
public ListServerviewmodel(Activity context) {
    this.context = context;
    this.servers = new ObservableArrayList<FtpServerviewmodel>();
    this.selectedServer = new ObservableField<FtpServerviewmodel>();
    this.selectedServerVisible = new ObservableBoolean();
}
项目:Architecture-Demo    文件:PostListComponentviewmodel.java   
@Inject
public PostListComponentviewmodel(Bus bus,IRepository repository,INavigator navigator,ILocalization localization) {
    super(bus);

    this.repository = repository;
    this.navigator = navigator;
    this.localization = localization;

    this.posts = new ObservableArrayList<>();

    this.isBusy = new ObservableBoolean();
    this.loadCommand = new Command(this::loadPosts);
}
项目:Cinder    文件:ObservableEventUnitTest.java   
@Test
public void fireNotifiesChange() throws Exception {
    ObservableEvent event = new ObservableEvent();
    ObservableBoolean fired = Cinder.computeBoolean(()->true,event);
    event.fire();

    assertTrue(fired.get());
}
项目:Cinder    文件:CinderUnitTest.java   
@Test
public void computesBoolean() throws Exception {
    boolean bool1 = true;
    boolean bool2 = false;
    ObservableBoolean truth = new ObservableBoolean(bool1);
    ObservableBoolean computedTruth = Cinder.computeBoolean(()->truth.get(),truth).immediate();
    assertEquals(computedTruth.get(),bool1);

    truth.set(bool2);
    assertEquals(computedTruth.get(),bool2);
}
项目:Cinder    文件:CinderBooleanUnitTest.java   
@Test
public void onceTakesOnce() throws Exception {
    String string1 = "STRING 1";
    String string2 = "STRING 2";
    ObservableField<String> observed = new ObservableField<>(string1);
    ObservableBoolean observing = Cinder.computeBoolean(()->
        observed.get().equals(string1),observed).once().immediate();
    assertTrue(observing.get());

    observed.set(string2);
    assertTrue(observing.get());
}
项目:Cinder    文件:CinderBooleanUnitTest.java   
@Test
public void filterFilters() throws Exception {
    String badString = "BAD STRING";
    String goodString = "GOOD STRING";
    ObservableField<String> observed = new ObservableField<>("");
    ObservableBoolean observing = Cinder.computeBoolean(()->
        observed.get().equals(goodString),observed).filter(()->observed.get().startsWith("GOOD"));

    observed.set(badString);
    assertFalse(observing.get());

    observed.set(goodString);
    assertTrue(observing.get());
}
项目:Cinder    文件:CinderBooleanUnitTest.java   
@Test
public void takeWhileTakesWhileTrue() throws Exception {
    String badString = "BAD STRING";
    String goodString = "GOOD STRING";
    ObservableField<String> observed = new ObservableField<>("");
    ObservableBoolean observing = Cinder.computeBoolean(()->
        observed.get().equals(goodString),observed).takeWhile(()->observed.get().startsWith("GOOD"));

    observed.set(goodString);
    assertTrue(observing.get());

    observed.set(badString);
    assertTrue(observing.get());
}
项目:Cinder    文件:CinderBooleanUnitTest.java   
@Test
public void skipwhileSkipsWhileTrue() throws Exception {
    String badString = "BAD STRING";
    String goodString = "GOOD STRING";
    ObservableField<String> observed = new ObservableField<>("");
    ObservableBoolean observing = Cinder.computeBoolean(()->
        observed.get().equals(goodString),observed).skipwhile(()->observed.get().startsWith("BAD"));

    observed.set(badString);
    assertFalse(observing.get());

    observed.set(goodString);
    assertTrue(observing.get());
}
项目:Cinder    文件:CinderBooleanUnitTest.java   
@Test
public void withDefaultAssignsDefault() throws Exception {
    ObservableBoolean observing = Cinder.computeBoolean(()->false
    ).withDefault(true);

    assertTrue(observing.get());
}
项目:Cinder    文件:RxCinderUnitTest.java   
@Test
public void convertsObservableBooleanToRx() throws Exception {
    ObservableBoolean observableBoolean = new ObservableBoolean();
    Observable<Boolean> rxBoolean = RxCinder.convert(observableBoolean);

    final String TEST_KEY = "TEST_KEY";
    final ArrayMap<String,Boolean> testMap = new ArrayMap<>();
    rxBoolean.subscribe((b)->{
        testMap.put(TEST_KEY,b);});

    observableBoolean.set(true);
    assertTrue(testMap.get(TEST_KEY));
}
项目:devfest-2016-realm    文件:Loginviewmodel.java   
public Loginviewmodel(LoginInteractor interactor,ProNavigator navigator) {
  this.interactor = interactor;
  this.navigator = navigator;

  email = new ObservableField<>();
  password = new ObservableField<>();
  passwordRepeat = new ObservableField<>();
  inProgress = new ObservableBoolean();
}
项目:DataBindingFormValidation    文件:Mainviewmodel.java   
/**
 * I would like to use this in the layout expressions,but there seems to be an issue related to this.
 * See https://code.google.com/p/android/issues/detail?id=230115
 */
public <T> void onFieldChanged(ObservableField<T> field,ObservableBoolean errorIndicator,boolean hasFocus,Validator<T> validator) {
    if (hasFocus) {
        errorIndicator.set(false);
    } else {
        T value = field.get();
        errorIndicator.set(!validator.validate(value));
        Log.d(TAG,"Field is invalid: " + errorIndicator.get());
        dataValid.set(validateForm());
    }
}
项目:rx-property-android    文件:RxCommandTest.java   
private static TestObserver<Boolean> observableBooleanTestObserver(RxCommand command) {
    return Observe.allPropertiesOf(command.getEnabled())
            .map(new Function<ObservableBoolean,Boolean>() {
                @Override
                public Boolean apply(ObservableBoolean value) throws Exception {
                    return value.get();
                }
            })
            .test();
}
项目:rx-property-android    文件:RxPropertyTest.java   
private static <T> TestObserver<Boolean> hasErrorObserver(final RxProperty<T> property) {
    return Observe.propertyOf(property.getHasError(),new Function<ObservableBoolean,Boolean>() {
                @Override
                public Boolean apply(ObservableBoolean value) throws Exception {
                    return value.get();
                }
            })
            .test();
}
项目:Anago    文件:StarredRepoListFragmentviewmodel.java   
@Inject
public StarredRepoListFragmentviewmodel(BaseFragment fragment,GetStarredReposUseCase getStarredReposUseCase,EventBus eventBus) {
    super(fragment);

    this.getStarredReposUseCase = getStarredReposUseCase;
    this.eventBus = eventBus;

    repos = new ObservableArrayList<>();
    isConnecting = new ObservableBoolean(true);
    isRefreshing = new ObservableBoolean(false);
}
项目:Anago    文件:RepoListItemviewmodel.java   
@Inject
public RepoListItemviewmodel(BaseFragment fragment,StarUseCase starUseCase,UnstarUseCase unstarUseCase,EventBus eventBus) {
    super(fragment);
    this.starUseCase = starUseCase;
    this.unstarUseCase = unstarUseCase;
    this.eventBus = eventBus;

    this.repo = new ObservableField<>();
    this.starred = new ObservableBoolean(false);
}
项目:Anago    文件:RepoInfoFragmentviewmodel.java   
@Inject
public RepoInfoFragmentviewmodel(BaseFragment fragment,GetRepoUseCase getRepoUseCase,CheckStarUseCase checkStarUseCase,EventBus eventBus) {
    super(fragment);
    this.getRepoUseCase = getRepoUseCase;
    this.checkStarUseCase = checkStarUseCase;
    this.starUseCase = starUseCase;
    this.unstarUseCase = unstarUseCase;
    this.eventBus = eventBus;

    this.repo = new ObservableField<>();
    this.isConnecting = new ObservableBoolean(true);
    this.starred = new ObservableBoolean(false);
}
项目:Anago    文件:UserActivityviewmodel.java   
@Inject
public UserActivityviewmodel(BaseActivity activity,GetUserUseCase getUserUseCase,EventBus eventBus) {
    super(activity);
    this.getUserUseCase = getUserUseCase;
    this.eventBus = eventBus;

    this.user = new ObservableField<>();
    this.isConnecting = new ObservableBoolean(true);
}
项目:Anago    文件:MyRepoListFragmentviewmodel.java   
@Inject
public MyRepoListFragmentviewmodel(BaseFragment fragment,GetUserReposUseCase getUserReposUseCase,EventBus eventBus) {
    super(fragment);

    this.getUserReposUseCase = getUserReposUseCase;
    this.eventBus = eventBus;

    repos = new ObservableArrayList<>();
    isConnecting = new ObservableBoolean(true);
    isRefreshing = new ObservableBoolean(false);
}
项目:Android-Code-Demos    文件:Employee.java   
public ObservableBoolean getIsFired() {
    return isFired;
}
项目:Android-Code-Demos    文件:Employee.java   
public void setIsFired(ObservableBoolean isFired) {
    this.isFired = isFired;
    notifyChange();
}
项目:Flubber    文件:RadioElementModel.java   
public ObservableBoolean getChecked() {
    return checked;
}
项目:Flubber    文件:RadioElementModel.java   
public void setChecked(ObservableBoolean checked) {
    this.checked = checked;
}
项目:android-mvvm-architecture    文件:Baseviewmodel.java   
public ObservableBoolean getIsLoading() {
    return mIsLoading;
}
项目:Android-HTTPS-based-on-MVVM    文件:Mainviewmodel.java   
public Mainviewmodel(Context context) {
    this.context = context;
    this.user = new UserBean();
    this.agree = new ObservableBoolean();
}
项目:Android-HTTPS-based-on-MVVM    文件:Mainviewmodel.java   
public ObservableBoolean getAgree() {
    return agree;
}
项目:RxDataBinding    文件:ObservableBooleanObservable.java   
ObservableBooleanObservable(ObservableBoolean observableBoolean) {
  this.observableBoolean = observableBoolean;
}
项目:AndroidAgeraTutorial    文件:VehicleInfo.java   
public VehicleInfo(ObservableBoolean isSelected,String logoUrl,String brand,String description) {
    this.isSelected = isSelected;
    this.logoUrl = logoUrl;
    this.brand = brand;
    this.description = description;
}
项目:SimpleFTP    文件:Fileviewmodel.java   
/**
 * Default constructor.
 * @param mainviewmodel The parent view model.
 */
public Fileviewmodel(Explorerviewmodel mainviewmodel) {
    this.mainviewmodel = mainviewmodel;
    this.isSelected = new ObservableBoolean(false);
}
项目:AndroidDataBindingTutorial    文件:VehicleInfo.java   
public VehicleInfo(ObservableBoolean isSelected,String description) {
    this.isSelected = isSelected;
    this.logoUrl = logoUrl;
    this.brand = brand;
    this.description = description;
}
项目:Architecture-Demo    文件:PostListComponentviewmodel.java   
public ObservableBoolean getIsBusy() {
    return isBusy;
}
项目:Architecture-Demo    文件:Command.java   
public Command(boolean canExecute,boolean isVisible,Action0 execute) {
    this.canExecute = new ObservableBoolean(canExecute);
    this.isVisible = new ObservableBoolean(isVisible);
    this.execute = execute;
}

android -------- Data Binding 的使用(三)Observable

android -------- Data Binding 的使用(三)Observable

解决:databinding 中 ViewModel 数据发生改变,View 中也要改变(实时更新)

 

BaseObservable

在 ViewModel 中可以继承 BaseObservable

public class User extends BaseObservable {

    public User(String frstName,String lastName){
        this.frstName = frstName;
        this.lastName = lastName;
        observableArrayMap.put("zq","zhhhhh");
        list.add("aaa");
        list.add("bbb");
    }

    private String frstName;

    private String lastName;

    public ObservableArrayMap<String,String> observableArrayMap = new ObservableArrayMap<>();

    public ObservableArrayList<String> list = new ObservableArrayList<>();

    @Bindable
    public String getFrstName() {
        return frstName;
    }


    public void setFrstName(String frstName) {
        this.frstName = frstName;
        //刷新UI
        notifyPropertyChanged(com.zhangqie.databinding.BR.frstName);
    }

    @Bindable
    public String getLastName() {
        return lastName;
    }


    public void setLastName(String lastName) {
        this.lastName = lastName;
        //全部刷新
        //notifyChange();
    }
}

在 set 方法里面,使用 notifyPropertyChanged 来通知 UI 刷新,notifyPropertyChanged 只会刷新具体的值,notifyChange 方法则会刷新所有的值。
BR 的域则是通过在 get 方法上加 @Bindable 生成的。

 

ObservableArrayMap

与 Java 的 Map 使用相同

public ObservableArrayMap<String,String> observableArrayMap = new ObservableArrayMap<>();

observableArrayMap.put("zq","zhhhhh");
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <variable
            name="user"
            type="com.zhangqie.databinding.demo2.User" />

    </data>

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

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=''@{user.observableArrayMap["zq"]}'' />

    </LinearLayout>

</layout>

ObservableArrayList

与 Java 的 List 使用相同

 public ObservableArrayList<String> list = new ObservableArrayList<>();
 list.add("aaa");
 list.add("bbb");

布局中:

       <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=''@{user.list[0]}'' />


        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.list[1]}" />

Observable Fields

继承自 BaseObservable 的方法有点复杂,DataBinding 还提供了一种简单的写法 —-ObservableField 来实现数据实时刷新

public class UserObservableBean {
    public ObservableInt userId = new ObservableInt();
    public ObservableField<String> userName = new ObservableField<>();
    public ObservableDouble userAge = new ObservableDouble();
    public ObservableFloat userSex = new ObservableFloat();
}

直接把属性定义成 ObservableField 类型的,并且修饰符需要是 public final 的。
除了 ObservableField,还可以使用 ObservableBoolean, ObservableByte, ObservableChar, ObservableShort, ObservableInt, ObservableLong, ObservableFloat, ObservableDouble, ObservableParcelable。
访问值得时候,可以使用 get set 方法。

UserObservableBean userBean = new UserObservableBean();
userBean.userId.set(8);
userBean.userName.set("切切心语");
userBean.userAge.set(25);

userBean.userId.get();
userBean.userName.get();
userBean.userAge.get();

这种方式就方便多了;

Android Data Binding 系列 (二) -- Binding 与 Observer 实现原理

Android Data Binding 系列 (二) -- Binding 与 Observer 实现原理

写在前面

上篇文章 Android Data Binding 系列 (一) -- 详细介绍与使用 介绍了 Data Binding 的基础及其用法,本文接上篇,结合 DataBindingDemo 来学习下 Data Binding 的实现。

绑定实现

Activity 在 inflate layout 时,通过 DataBindingUtil 来生成绑定,从代码看,是遍历 contentView 得到 View 数组对象,然后通过数据绑定 library 生成对应的 Binding 类,含 Views、变量、listeners 等。生成类位于 build/intermediates/classes/debug/...package.../databinding/xxx.java 下,具体如何生成这里暂不作深入。

绑定过程

  • 首先,会在父类(ViewDataBinding)中实例化回调或 Handler,用于之后的绑定操作;
private static final boolean USE_CHOREOGRAPHER = SDK_INT >= 16;

if (USE_CHOREOGRAPHER) {
    mChoreographer = Choreographer.getInstance();
    mFrameCallback = new Choreographer.FrameCallback() {
        @Override
        public void doFrame(long frameTimeNanos) {
            mRebindRunnable.run();
        }
    };
} else {
    mFrameCallback = null;
    mUIThreadHandler = new Handler(Looper.myLooper());
}
  • 接着,通过调用 mapBindings(...) 遍历布局以获得包含 bound、includes、ID Views 的数组对象,再依次赋给对应 View
final Object[] bindings = mapBindings(bindingComponent, root, 3, sIncludes, sViewsWithIds);
this.mboundView0 = (android.widget.LinearLayout) bindings[0];
this.mboundView0.setTag(null);
  • 然后,调用 invalidateAll() -> requestRebind() -> ... -> mRebindRunnable.run() - 执行 Runnable
// 用于动态重新绑定 Views
private final Runnable mRebindRunnable = new Runnable() {
    @Override
    public void run() {
        synchronized (this) {
            mPendingRebind = false;
        }
        .....
        executePendingBindings();
    }
};
  • 最后,通过该 Runnable 会执行到 executePendingBindings() -> ... -> executeBindings(),在这里会执行绑定相关操作。
@Override
protected void executeBindings() {
    long dirtyFlags = 0;
    synchronized(this) {
        dirtyFlags = mDirtyFlags;   // mDirtyFlags 变量更新的标志
        mDirtyFlags = 0;
    }
    .....
}

设置变量 (数据对象)

普通 Java bean 对象

  • 首先,通过 mDirtyFlags 标识变量 (所有变量共用)
synchronized(this) {
    mDirtyFlags |= 0x1L;
}
  • 然后,调用 notifyPropertyChanged(...) 来通知更新(若有回调)
public void notifyPropertyChanged(int fieldId) {
    if (mCallbacks != null) {
        mCallbacks.notifyCallbacks(this, fieldId, null);
    }
}
  • 最后,调用 requestRebind() -> ... -> executeBindings() 再次执行绑定操作,将数据更新到 Views 上
@Override
protected void executeBindings() {
    long dirtyFlags = 0;
    synchronized(this) {
        dirtyFlags = mDirtyFlags;
        mDirtyFlags = 0;
    }
    .....
}

Observable 对象

  • 在设置变量时,会先调用 updateRegistration(..) 注册一个 Observable 对象的监听
public void setContact(com.connorlin.databinding.model.ObservableContact contact) {
    updateRegistration(0, contact);
    this.mContact = contact;
    synchronized(this) {
        mDirtyFlags |= 0x1L;
    }
    notifyPropertyChanged(BR.contact);
    super.requestRebind();
}
  • 其他步骤同普通 Java bean 对象

ObservableFields 对象

  • 前期步骤同普通 Java Bean 对象

  • 与 Observable 对象不同的是,Observable 对象的监听是在 executeBindings() 中注册的

@Override
protected void executeBindings() {
    long dirtyFlags = 0;
    synchronized(this) {
        dirtyFlags = mDirtyFlags;
        mDirtyFlags = 0;
    }
    ...
    if ((dirtyFlags & 0xfL) != 0) {
        if ((dirtyFlags & 0xdL) != 0) {
            if (contact != null) {
                // read contact.mName
                mNameContact = contact.mName;
            }
            updateRegistration(0, mNameContact);

            if (mNameContact != null) {
                // read contact.mName.get()
                mNameContact1 = mNameContact.get();
            }
        }
        ...
    }
    ...
}

注册 Observable 对象监听

  • 入口 updateRegistration(0, contact)
protected boolean updateRegistration(int localFieldId, Observable observable) {
    return updateRegistration(localFieldId, observable, CREATE_PROPERTY_LISTENER);
}

private boolean updateRegistration(int localFieldId, Object observable,
        CreateWeakListener listenerCreator) {
    ...
    // 确保不重复监听,先移除再添加观察监听
    unregisterFrom(localFieldId);
    registerTo(localFieldId, observable, listenerCreator);
    return true;
}

protected void registerTo(int localFieldId, Object observable,
        CreateWeakListener listenerCreator) {
    if (observable == null) {
        return;
    }

    // 创建对象监听并存到mLocalFieldObservers中
    WeakListener listener = mLocalFieldObservers[localFieldId];
    if (listener == null) {
        // CREATE_PROPERTY_LISTENER -> create(...)
        listener = listenerCreator.create(this, localFieldId);
        mLocalFieldObservers[localFieldId] = listener;
    }

    // 将监听绑定到Observable对象上
    listener.setTarget(observable);
}

每个 Observable 对象都会添加一个观察监听,保存在数组 mLocalFieldObservers 中,并以 localFieldId 索引。

  • CREATE_PROPERTY_LISTENER 为何物?
private static final CreateWeakListener CREATE_PROPERTY_LISTENER = new CreateWeakListener() {
    @Override
    public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
        // 返回从WeakPropertyListener实例中获取的监听器(WeakListener)
        return new WeakPropertyListener(viewDataBinding, localFieldId).getListener();
    }
}

private static class WeakPropertyListener extends Observable.OnPropertyChangedCallback
        implements ObservableReference<Observable> {
    final WeakListener<Observable> mListener;

    public WeakPropertyListener(ViewDataBinding binder, int localFieldId) {
        mListener = new WeakListener<Observable>(binder, localFieldId, this);
    }

    @Override
    public WeakListener<Observable> getListener() {
        return mListener;
    }

    @Override
    public void addListener(Observable target) {
        // WeakPropertyListener 继承于 Observable.OnPropertyChangedCallback,
        // 所以 this 其实就是 Observable对象的属性监听器
        target.addOnPropertyChangedCallback(this);
    }

    ...
}

private static class WeakListener<T> extends WeakReference<ViewDataBinding> {
    private final ObservableReference<T> mObservable;
    protected final int mLocalFieldId;
    private T mTarget;

    ...

    public void setTarget(T object) {
        unregister();
        mTarget = object;
        if (mTarget != null) {
            // mObservable 是上面的 WeakPropertyListener对象
            // mTarget 是绑定到listener上得Observable对象
            mObservable.addListener(mTarget);
        }
    }

    ...
}

CREATE_PROPERTY_LISTENER 实际上只是一个接口实例,注册时会调用它的 create() 方法创建一个弱引用 listener,它的作用是将 listener 绑定到 Observable 对象上, 绑定时,会调用 listener.setTarget(...) 将 Observable 对象传给 WeakPropertyListener 实例,然后,WeakPropertyListener 会为 Observable 对象添加 OnPropertyChangedCallback

  • addOnPropertyChangedCallback 实现

addOnPropertyChangedCallback 在 BaseObservable 中实现,首先会实例化一个 PropertyChangeRegistry 对象,同时创建一个用来通知 Observable 对象重新绑定更新的回调 CallbackRegistry.NotifierCallback。然后将 OnPropertyChangedCallback 添加到 PropertyChangeRegistry 的回调列表中

@Override
public synchronized void addOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
    if (mCallbacks == null) {
        mCallbacks = new PropertyChangeRegistry();
    }
    mCallbacks.add(callback);
}

这样,注册 Observable 对象的监听就完毕了。

更新 (重新绑定) Observable 对象

设置或更新 Observable 对象时都会调用 notifyPropertyChanged()notifyChange() 来通知更新,那到底是如何更新的呢?

  • 回调过程
public void notifyPropertyChanged(int fieldId) {
    // mCallbacks 是 PropertyChangeRegistry对象,在 addOnPropertyChangedCallback 时实例化
    // 如果注册了Observable对象监听,那么mCallbacks不为null
    if (mCallbacks != null) {
        mCallbacks.notifyCallbacks(this, fieldId, null);
    }
}

// baseLibrary
private void notifyCallbacks(T sender, int arg, A arg2, int startIndex, int endIndex, long bits) {
    long bitMask = 1L;
    for(int i = startIndex; i < endIndex; ++i) {
        if((bits & bitMask) == 0L) {
            // mNotifier 是实例化PropertyChangeRegistry时创建的
            // mNotifier 即 CallbackRegistry.NotifierCallback
            this.mNotifier.onNotifyCallback(this.mCallbacks.get(i), sender, arg, arg2);
        }
        bitMask <<= 1;
    }
}

// PropertyChangeRegistry.NOTIFIER_CALLBACK
public void onNotifyCallback(Observable.OnPropertyChangedCallback callback, Observable sender,
        int arg, Void notUsed) {
    // callback 是为Observable对象添加的OnPropertyChangedCallback,即WeakPropertyListener
    callback.onPropertyChanged(sender, arg);
}

// WeakPropertyListener
public void onPropertyChanged(Observable sender, int propertyId) {
    // binder 即生成的Binding类对象
    ViewDataBinding binder = mListener.getBinder();
    ...
    binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId);
}

private void handleFieldChange(int mLocalFieldId, Object object, int fieldId) {
    // onFieldChange 实现在生成的Binding类中
    boolean result = onFieldChange(mLocalFieldId, object, fieldId);
    if (result) {
        // 如果对象属性变化,将重新绑定
        requestRebind();
    }
}

通过 notifyPropertyChanged 调用到 mNotifier 回调, mNotifier 通知 OnPropertyChangedCallback Observable 对象属性发生变化,然后在 onPropertyChanged 中又转给 ViewDataBinding 对象 (生成的 Binding 类) 处理。

  • 判断是否需要重新绑定并执行,在生成的 Binding 类中实现
// 生成的Binding类中得方法
protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {
    // 如果变量不是Observable类型或没有添加 Bindable注解,就不会判断,直接返回false
    switch (localFieldId) {
        case 0 :
            return onChangeContact((com.connorlin.databinding.model.ObservableContact) object, fieldId);
    }
    return false;
}

private boolean onChangeContact(com.connorlin.databinding.model.ObservableContact contact, int fieldId) {
    switch (fieldId) {
        case BR.name: {
            synchronized(this) {
                    mDirtyFlags |= 0x4L;// 通过mDirtyFlags判断对象是否变化
            }
            return true;
        }
        ...
    }
    return false;
}

至此,更新过程完毕。

整个注册与更新过程可以用一张流程图来概括:

事件处理

事件处理的原理很简单,在生成 Binding 类中会实现 View 事件的监听,在构造时实例化 View 的事件监听,然后在绑定时将事件监听对象赋值给对应 View,这样,点击时就会触发相应的监听。

这里以 DataBindingDemo 中 EventActivity 部分为例:

  • 生成的 Binding 类并实现 View 的事件监听
public class ActivityEventBinding extends android.databinding.ViewDataBinding
    implements android.databinding.generated.callback.OnCheckedChangeListener.Listener,
        android.databinding.generated.callback.OnClickListener.Listener {
    // Checkbox check监听
    private final android.widget.CompoundButton.OnCheckedChangeListener mCallback3;
    private final android.view.View.OnClickListener mCallback2;
    private final android.view.View.OnClickListener mCallback1;
    // listeners
    private OnClickListenerImpl mAndroidViewViewOnCl;
    ...
    // Listener Stub Implementations
    public static class OnClickListenerImpl implements android.view.View.OnClickListener{
        private com.connorlin.databinding.handler.EventHandler value;
        public OnClickListenerImpl setValue(com.connorlin.databinding.handler.EventHandler value) {
            this.value = value;
            return value == null ? null : this;
        }
        @Override
        public void onClick(android.view.View arg0) {
            this.value.onClickFriend(arg0);
        }
    }
    ...
}
  • 实例化 View 的事件监听
public ActivityEventBinding(android.databinding.DataBindingComponent bindingComponent, View root) {
    super(bindingComponent, root, 0);
    ...
    // listeners
    mCallback3 = new android.databinding.generated.callback.OnCheckedChangeListener(this, 3);
    mCallback2 = new android.databinding.generated.callback.OnClickListener(this, 2);
    mCallback1 = new android.databinding.generated.callback.OnClickListener(this, 1);
    invalidateAll();
}
  • 在执行绑定中绑定 View 事件监听
@Override
protected void executeBindings() {
    ...
    if ((dirtyFlags & 0x6L) != 0) {
        if (handler != null) {
            // read handler::onClickFriend
            androidViewViewOnCli = (((mAndroidViewViewOnCl == null)
                ? (mAndroidViewViewOnCl = new OnClickListenerImpl()) : mAndroidViewViewOnCl).setValue(handler));
        }
    }
    // batch finished
    if ((dirtyFlags & 0x6L) != 0) {
        this.mboundView1.setOnClickListener(androidViewViewOnCli);
    }
    if ((dirtyFlags & 0x4L) != 0) {
        this.mboundView2.setOnClickListener(mCallback1);
        this.mboundView3.setOnClickListener(mCallback2);
        android.databinding.adapters.CompoundButtonBindingAdapter.setListeners(
            this.mboundView4, mCallback3, (android.databinding.InverseBindingListener)null);
    }
}
  • 触发事件并执行

ViewStub

原理类似,只是利用 ViewStubProxy 来延迟绑定。

  • 使用 layout 中的 ViewStub 实例化一个 ViewStubProxy 对象赋给 viewstub 变量,并与 Bingding 关联
public ActivityViewStubBinding(android.databinding.DataBindingComponent bindingComponent, View root) {
    super(bindingComponent, root, 0);
    final Object[] bindings = mapBindings(bindingComponent, root, 2, sIncludes, sViewsWithIds);
    ...
    this.viewStub = new android.databinding.ViewStubProxy((android.view.ViewStub) bindings[1]);
    this.viewStub.setContainingBinding(this);
    ...
}
  • 实例化 ViewStubProxy 的同时会注册 inflate 监听
private OnInflateListener mProxyListener = new OnInflateListener() {
    @Override
    public void onInflate(ViewStub stub, View inflated) {
        mRoot = inflated;
        mViewDataBinding = DataBindingUtil.bind(mContainingBinding.mBindingComponent,
                inflated, stub.getLayoutResource());
        mViewStub = null;

        if (mOnInflateListener != null) {
            mOnInflateListener.onInflate(stub, inflated);
            mOnInflateListener = null;
        }
        mContainingBinding.invalidateAll();
        mContainingBinding.forceExecuteBindings();
    }
};

public ViewStubProxy(ViewStub viewStub) {
    mViewStub = viewStub;
    mViewStub.setOnInflateListener(mProxyListener);
}
  • inflate ViewStub
if (!mActivityViewStubBinding.viewStub.isInflated()) {
    mActivityViewStubBinding.viewStub.getViewStub().inflate();
}

当 ViewStub infate 时,执行 mProxyListener,其中会生成 ViewStub 的 Binding,并强制执行主 Binding 重绑

  • 绑定 ViewStub
@Override
protected void executeBindings() {
    long dirtyFlags = 0;
    synchronized(this) {
        dirtyFlags = mDirtyFlags;
        mDirtyFlags = 0;
    }
    // batch finished
    if (viewStub.getBinding() != null) {
        viewStub.getBinding().executePendingBindings();
    }
}

这样,ViewStub 绑定就结束了。

本篇完,敬请期待下篇...


我的简书账号是 ConnorLin,欢迎关注!

我的简书专题是 Android 开发技术分享,欢迎关注!

我的个人博客 欢迎关注!

原创文章,欢迎转载,转载请注明出处!

欢迎您扫一扫上面的微信公众号,订阅我的博客!

Android Studio 4.0.1:构建失败:不建议使用“ android.databinding.enableV2”选项

Android Studio 4.0.1:构建失败:不建议使用“ android.databinding.enableV2”选项

gradle.properties中删除这些行:

android.enableExperimentalFeatureDatabinding=false
android.databinding.enableV2=false

并修复您正确添加它们的原因(“无法猜测” ...)。另请参见是否另一个模块可能不使用选项android.databinding.enableV2并尝试手动删除构建缓存并构建目录一次。更新IDE只会更新Gradle插件版本,它当然不会改变其他任何东西。如果您有这样的担忧,则可能应该使用某种版本控制系统,该系统以diff的形式显示所有更改(这还提供了无限的撤消功能和许多其他有用的功能); Android Studio支持不带插件的功能。

,

问题在于该行:

android.databinding.enableV2 = false

必须从我的 HOME 目录中的gradle-properties文件中删除。在MAC上,它位于此处:

〜/ .gradle

android – Observable返回类型必须参数化为Observable或Observable

android – Observable返回类型必须参数化为Observable或Observable

我正在使用改造2.0.0-beta2并且调试版本正常工作但我在使用Proguard进行发布版本时遇到以下错误.

这是更新的logcat错误.

11-17 18:23:22.751 16274-16274/ph.reggis.FEDT D/AndroidRuntime: Shutting down VM
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime: FATAL EXCEPTION: main
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime: Process: ph.reggis.FEDT,PID: 16274
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime: java.lang.RuntimeException: Unable to resume activity {ph.reggis.FEDT/ph.reggis.FEDT.view.activity.NotificationListActivity}: java.lang.IllegalArgumentException: Unable to create call adapter for class b.a
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     for method InsularFMService.getNews
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3103)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3134)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2481)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at android.app.ActivityThread.-wrap11(ActivityThread.java)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:102)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:148)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5417)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:  Caused by: java.lang.IllegalArgumentException: Unable to create call adapter for class b.a
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     for method InsularFMService.getNews
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at retrofit.Utils.methodError(UnkNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at retrofit.MethodHandler.createCallAdapter(UnkNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at retrofit.MethodHandler.create(UnkNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at retrofit.Retrofit.loadMethodHandler(UnkNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at retrofit.Retrofit$1.invoke(UnkNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at java.lang.reflect.Proxy.invoke(Proxy.java:393)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at $Proxy0.getNews(UnkNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at ph.reggis.FEDT.b.C.d(UnkNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at ph.reggis.FEDT.view.fragment.NotificationListFragment.t(UnkNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at ph.reggis.FEDT.view.fragment.NotificationListFragment.l(UnkNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at android.support.v4.b.B.a(UnkNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at android.support.v4.b.B.a(UnkNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at android.support.v4.b.B.a(UnkNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at android.support.v4.b.B.i(UnkNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at android.support.v4.b.y.i(UnkNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at android.support.v4.b.t.onPostResume(UnkNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at android.support.v7.a.B.onPostResume(UnkNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at android.app.Activity.performResume(Activity.java:6336)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3092)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:  Caused by: java.lang.IllegalStateException: Observable return type must be parameterized as ObservableNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at retrofit.Retrofit.nextCallAdapter(UnkNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:     at retrofit.Retrofit.callAdapter(UnkNown Source)
11-17 18:23:22.752 16274-16274/ph.reggis.FEDT E/AndroidRuntime:         ... 28 more

接口:

@GET("news")
Observable

分段:

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(Constant.WS_URL_BASE)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .build();

InsularFMService fmService = retrofit.create(InsularFMService.class);

//Observable

Graddle:

compile "com.squareup.retrofit:retrofit:2.0.0-beta2"
compile "com.squareup.retrofit:converter-gson:2.0.0-beta2"
compile "com.squareup.retrofit:adapter-rxjava:2.0.0-beta2"

Proguard的:

# Fixed: Caused by: java.lang.NoSuchFieldException: No field producerIndex
 -keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
     long producerIndex;
     long consumerIndex;
 }
 -keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
     long producerNode;
     long consumerNode;
}
最佳答案
现在它正在将这些属性放在Proguard中.

# Application classes that will be serialized/deserialized over Gson
-keep class ph.reggis.FEDT.model.api.** { *; }

这是完整的设置

##---------------Begin: proguard configuration for Gson  ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default,so configure it to keep all of it.
-keepattributes Signature
-keepattributes *Annotation*

# Gson specific classes
-keep class sun.misc.Unsafe { *; }

# Application classes that will be serialized/deserialized over Gson
-keep class ph.reggis.FEDT.model.api.** { *; }

##---------------End: proguard configuration for Gson  ----------

今天的关于android.databinding.ObservableBoolean的实例源码android data obb的分享已经结束,谢谢您的关注,如果想了解更多关于android -------- Data Binding 的使用(三)Observable、Android Data Binding 系列 (二) -- Binding 与 Observer 实现原理、Android Studio 4.0.1:构建失败:不建议使用“ android.databinding.enableV2”选项、android – Observable返回类型必须参数化为Observable或Observable的相关知识,请在本站进行查询。

本文标签: