diff --git a/adapters/build.gradle b/adapters/build.gradle index 73e6c8c..3d302bc 100644 --- a/adapters/build.gradle +++ b/adapters/build.gradle @@ -16,6 +16,10 @@ android { targetSdkVersion sdkVersion project.archivesBaseName = "android-adapters" } + + dataBinding { + enabled = true + } } dependencies { diff --git a/adapters/src/main/java/io/realm/RealmObjectDataBindingListener.java b/adapters/src/main/java/io/realm/RealmObjectDataBindingListener.java new file mode 100644 index 0000000..b5ee314 --- /dev/null +++ b/adapters/src/main/java/io/realm/RealmObjectDataBindingListener.java @@ -0,0 +1,72 @@ +package io.realm; + +import android.app.Activity; +import android.databinding.BaseObservable; + +import java.util.ArrayList; +import java.util.List; + +public abstract class RealmObjectDataBindingListener implements RealmObjectChangeListener { + + private final BaseObservable observable; + private final List fieldNames; + private final List fieldIds; + + private RealmObjectDataBindingListener(BaseObservable observable, + List fieldNames, List fieldIds) { + this.observable = observable; + this.fieldNames = fieldNames; + this.fieldIds = fieldIds; + } + + @Override + public void onChange(T t, ObjectChangeSet objectChangeSet) { + if (objectChangeSet.isDeleted()) { + onDeleted(); + return; + } + + for (ObjectChangeSet.FieldChange fieldChange : objectChangeSet.getFieldChanges()) { + int index = fieldNames.indexOf(fieldChange.fieldName); + if (index != -1) { + observable.notifyPropertyChanged(fieldIds.get(index)); + } + } + } + + public abstract void onDeleted(); + + + public static class Builder { + private BaseObservable observable; + private List fieldNames = new ArrayList(); + private List fieldIds = new ArrayList(); + private Runnable runnable = null; + + public Builder(BaseObservable observable) { + this.observable = observable; + } + + public Builder observe(String fieldName, int fieldId) { + fieldNames.add(fieldName); + fieldIds.add(fieldId); + return this; + } + + public Builder onDeleted(Runnable runnable) { + this.runnable = runnable; + return this; + } + + public RealmObjectDataBindingListener build() { + return new RealmObjectDataBindingListener(observable, fieldNames, fieldIds) { + @Override + public void onDeleted() { + if (runnable != null) { + runnable.run(); + } + } + }; + } + } +} diff --git a/build.gradle b/build.gradle index a192108..7cb1f89 100644 --- a/build.gradle +++ b/build.gradle @@ -4,15 +4,13 @@ buildscript { ext { sdkVersion = 25 buildTools = '25.0.0' - realmVersion = '3.0.0' + realmVersion = '3.1.0-SNAPSHOT' supportLibraryVersion = '25.2.0' } repositories { jcenter() - maven { - url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' - } + mavenLocal() } dependencies { classpath 'com.android.tools.build:gradle:2.3.0' // Android Build tools @@ -35,9 +33,7 @@ allprojects { version = file("${rootDir}/version.txt").text.trim(); repositories { jcenter() - maven { - url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' - } + mavenLocal() } } diff --git a/example/build.gradle b/example/build.gradle index 09e1306..d6d941e 100644 --- a/example/build.gradle +++ b/example/build.gradle @@ -21,10 +21,15 @@ android { command { events 2000 } + + dataBinding { + enabled = true + } } dependencies { compile project(':adapters') compile "com.android.support:appcompat-v7:${supportLibraryVersion}" compile "com.android.support:recyclerview-v7:${supportLibraryVersion}" + compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha5' } diff --git a/example/src/main/AndroidManifest.xml b/example/src/main/AndroidManifest.xml index 54547fa..ce7e765 100644 --- a/example/src/main/AndroidManifest.xml +++ b/example/src/main/AndroidManifest.xml @@ -7,13 +7,13 @@ android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> - + @@ -23,6 +23,14 @@ + + + + diff --git a/example/src/main/java/io/realm/examples/adapters/MainActivity.java b/example/src/main/java/io/realm/examples/adapters/MainActivity.java index 2a1f9ba..480591c 100644 --- a/example/src/main/java/io/realm/examples/adapters/MainActivity.java +++ b/example/src/main/java/io/realm/examples/adapters/MainActivity.java @@ -22,6 +22,7 @@ import android.support.v7.app.AppCompatActivity; import android.view.View; +import io.realm.examples.adapters.ui.databinding.OwnerListActivity; import io.realm.examples.adapters.ui.listview.ListViewExampleActivity; import io.realm.examples.adapters.ui.recyclerview.RecyclerViewExampleActivity; @@ -35,6 +36,7 @@ protected void onCreate(Bundle savedInstanceState) { setupButton(R.id.button_listview, ListViewExampleActivity.class); setupButton(R.id.button_recyclerview, RecyclerViewExampleActivity.class); + setupButton(R.id.button_data_binding, OwnerListActivity.class); } void startActivity(Class activityClass) { diff --git a/example/src/main/java/io/realm/examples/adapters/model/DataHelper.java b/example/src/main/java/io/realm/examples/adapters/model/DataHelper.java index 1c7c233..d78283e 100644 --- a/example/src/main/java/io/realm/examples/adapters/model/DataHelper.java +++ b/example/src/main/java/io/realm/examples/adapters/model/DataHelper.java @@ -65,4 +65,15 @@ public void execute(Realm realm) { } }); } + + public static void addOwnerAsync(Realm realm, final int count) { + realm.executeTransactionAsync(new Realm.Transaction() { + @Override + public void execute(Realm realm) { + for (int i = 0; i < count; i++) { + realm.copyToRealm(Owner.create()); + } + } + }); + } } diff --git a/example/src/main/java/io/realm/examples/adapters/model/Dog.java b/example/src/main/java/io/realm/examples/adapters/model/Dog.java new file mode 100644 index 0000000..dcb9fc1 --- /dev/null +++ b/example/src/main/java/io/realm/examples/adapters/model/Dog.java @@ -0,0 +1,15 @@ +package io.realm.examples.adapters.model; + +import io.realm.RealmObject; + +public class Dog extends RealmObject { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/example/src/main/java/io/realm/examples/adapters/model/Owner.java b/example/src/main/java/io/realm/examples/adapters/model/Owner.java new file mode 100644 index 0000000..1da4a69 --- /dev/null +++ b/example/src/main/java/io/realm/examples/adapters/model/Owner.java @@ -0,0 +1,46 @@ +package io.realm.examples.adapters.model; + +import java.util.concurrent.atomic.AtomicInteger; + +import io.realm.RealmObject; +import io.realm.annotations.PrimaryKey; + +public class Owner extends RealmObject { + @PrimaryKey + private int id; + private String name; + private Dog dog; + + private static AtomicInteger counter = new AtomicInteger(0); + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Dog getDog() { + return dog; + } + + public void setDog(Dog dog) { + this.dog = dog; + } + + public static Owner create() { + int id = counter.getAndIncrement(); + Dog dog = new Dog(); + dog.setName("Dog-" + id); + Owner owner = new Owner(); + owner.id = id; + owner.setName("Owner-" + id); + owner.setDog(dog); + return owner; + } +} diff --git a/example/src/main/java/io/realm/examples/adapters/ui/databinding/OwnerDetailsActivity.java b/example/src/main/java/io/realm/examples/adapters/ui/databinding/OwnerDetailsActivity.java new file mode 100644 index 0000000..f8bd7fe --- /dev/null +++ b/example/src/main/java/io/realm/examples/adapters/ui/databinding/OwnerDetailsActivity.java @@ -0,0 +1,54 @@ +package io.realm.examples.adapters.ui.databinding; + +import android.databinding.DataBindingUtil; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; + +import io.realm.Realm; +import io.realm.RealmObjectDataBindingListener; +import io.realm.examples.adapters.R; +import io.realm.examples.adapters.databinding.ActivityOwnerDetailsBinding; +import io.realm.examples.adapters.model.Dog; +import io.realm.examples.adapters.model.Owner; + +public class OwnerDetailsActivity extends AppCompatActivity { + + public static String EXTRA_DATA_OWNER_ID = "owner_id"; + + private Realm realm; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + realm = Realm.getDefaultInstance(); + int id = getIntent().getIntExtra(EXTRA_DATA_OWNER_ID, -1); + Owner owner = realm.where(Owner.class).equalTo("id", id).findFirst(); + Dog dog = owner.getDog(); + + final ActivityOwnerDetailsBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_owner_details); + binding.setOwner(owner); + binding.setDog(owner.getDog()); + + owner.addChangeListener( + new RealmObjectDataBindingListener.Builder(binding) + .observe("name", R.id.owner_name_text_edit) + .onDeleted(new Runnable() { + @Override + public void run() { + finish(); + } + }) + .build()); + dog.addChangeListener( + new RealmObjectDataBindingListener.Builder(binding) + .observe("name", R.id.dog_name_text_edit) + .build()); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + realm.close(); + } +} diff --git a/example/src/main/java/io/realm/examples/adapters/ui/databinding/OwnerListActivity.java b/example/src/main/java/io/realm/examples/adapters/ui/databinding/OwnerListActivity.java new file mode 100644 index 0000000..0e326a3 --- /dev/null +++ b/example/src/main/java/io/realm/examples/adapters/ui/databinding/OwnerListActivity.java @@ -0,0 +1,64 @@ +package io.realm.examples.adapters.ui.databinding; + +import android.os.Bundle; +import android.app.Activity; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.Menu; +import android.view.MenuItem; + +import io.realm.Realm; +import io.realm.RealmResults; +import io.realm.examples.adapters.R; +import io.realm.examples.adapters.model.DataHelper; +import io.realm.examples.adapters.model.Owner; +import io.realm.examples.adapters.ui.DividerItemDecoration; + +public class OwnerListActivity extends AppCompatActivity { + + private Realm realm; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_owner_list); + realm = Realm.getDefaultInstance(); + + setUpRecyclerView((RecyclerView) findViewById(R.id.recycler_view)); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + realm.close(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.owner_list_view_options, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int id = item.getItemId(); + switch (id) { + case R.id.action_add: + DataHelper.addOwnerAsync(realm, 1); + return true; + default: + break; + } + return false; + } + + private void setUpRecyclerView(RecyclerView recyclerView) { + RealmResults results = realm.where(Owner.class).findAllAsync(); + OwnerListViewAdapter adapter = new OwnerListViewAdapter(results); + + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + recyclerView.setAdapter(adapter); + recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST)); + } +} diff --git a/example/src/main/java/io/realm/examples/adapters/ui/databinding/OwnerListViewAdapter.java b/example/src/main/java/io/realm/examples/adapters/ui/databinding/OwnerListViewAdapter.java new file mode 100644 index 0000000..cc271ab --- /dev/null +++ b/example/src/main/java/io/realm/examples/adapters/ui/databinding/OwnerListViewAdapter.java @@ -0,0 +1,56 @@ +package io.realm.examples.adapters.ui.databinding; + +import android.content.Intent; +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import io.realm.OrderedRealmCollection; +import io.realm.RealmRecyclerViewAdapter; +import io.realm.examples.adapters.R; +import io.realm.examples.adapters.model.Owner; + + +class OwnerListViewAdapter extends RealmRecyclerViewAdapter { + + static class ViewHolder extends RecyclerView.ViewHolder { + private Owner owner; + private TextView textView; + + View.OnClickListener onClickListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(v.getContext(), OwnerDetailsActivity.class); + intent.putExtra(OwnerDetailsActivity.EXTRA_DATA_OWNER_ID, owner.getId()); + v.getContext().startActivity(intent); + } + }; + + ViewHolder(final View itemView) { + super(itemView); + this.textView = (TextView) itemView.findViewById(R.id.owner_name_view); + itemView.setOnClickListener(onClickListener); + } + } + + public OwnerListViewAdapter(@Nullable OrderedRealmCollection data) { + super(data, true); + } + + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View itemView = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.owner_list_row, parent, false); + return new ViewHolder(itemView); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + holder.owner = getItem(position); + holder.textView.setText(holder.owner.getName()); + } +} diff --git a/example/src/main/res/layout/activity_main.xml b/example/src/main/res/layout/activity_main.xml index 36b4911..035352a 100644 --- a/example/src/main/res/layout/activity_main.xml +++ b/example/src/main/res/layout/activity_main.xml @@ -20,4 +20,10 @@ android:layout_height="wrap_content" android:text="@string/recyclerview"/> - +