diff --git a/build.gradle b/build.gradle index 1b7886d..a60bf2e 100644 --- a/build.gradle +++ b/build.gradle @@ -15,5 +15,6 @@ buildscript { allprojects { repositories { jcenter() + maven { url "https://jitpack.io" } } } diff --git a/example/app/build.gradle b/example/app/build.gradle index 254885a..7fbbc01 100644 --- a/example/app/build.gradle +++ b/example/app/build.gradle @@ -1,4 +1,6 @@ apply plugin: 'com.android.application' +// This does not break the build when Android Studio is missing the JRebel for Android plugin. +apply plugin: 'com.zeroturnaround.jrebel.android' android { compileSdkVersion 22 diff --git a/example/app/src/main/AndroidManifest.xml b/example/app/src/main/AndroidManifest.xml index e626243..7af6e55 100644 --- a/example/app/src/main/AndroidManifest.xml +++ b/example/app/src/main/AndroidManifest.xml @@ -20,6 +20,10 @@ android:name=".MainActivity" android:label="@string/app_name" > + + diff --git a/example/app/src/main/java/co/moonmonkeylabs/realmrecyclerview/example/LayoutSelectorActivity.java b/example/app/src/main/java/co/moonmonkeylabs/realmrecyclerview/example/LayoutSelectorActivity.java index 2c71e82..7e670fe 100644 --- a/example/app/src/main/java/co/moonmonkeylabs/realmrecyclerview/example/LayoutSelectorActivity.java +++ b/example/app/src/main/java/co/moonmonkeylabs/realmrecyclerview/example/LayoutSelectorActivity.java @@ -28,6 +28,20 @@ public void onClick(View v) { } ); + final Button linearWithLoadMoreButton = + (Button) findViewById(R.id.recycler_linear_with_load_more_button); + linearWithLoadMoreButton.setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(LayoutSelectorActivity.this, MainActivity.class); + intent.putExtra("Type", "LinearLoadMore"); + startActivity(intent); + } + } + ); + + final Button gridButton = (Button) findViewById(R.id.recycler_grid_button); gridButton.setOnClickListener( new View.OnClickListener() { @@ -39,5 +53,17 @@ public void onClick(View v) { } } ); + + final Button sectionButton = (Button) findViewById(R.id.recycler_section_header_button); + sectionButton.setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(LayoutSelectorActivity.this, MainActivity2.class); + intent.putExtra("Type", "Header (SLM) "); + startActivity(intent); + } + } + ); } } diff --git a/example/app/src/main/java/co/moonmonkeylabs/realmrecyclerview/example/MainActivity.java b/example/app/src/main/java/co/moonmonkeylabs/realmrecyclerview/example/MainActivity.java index 8cc61a7..42c513f 100644 --- a/example/app/src/main/java/co/moonmonkeylabs/realmrecyclerview/example/MainActivity.java +++ b/example/app/src/main/java/co/moonmonkeylabs/realmrecyclerview/example/MainActivity.java @@ -5,15 +5,13 @@ import android.os.AsyncTask; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.GridLayoutManager; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.TextView; +import android.widget.Toast; import java.util.Arrays; import java.util.List; @@ -24,6 +22,7 @@ import io.realm.RealmBasedRecyclerViewAdapter; import io.realm.RealmConfiguration; import io.realm.RealmResults; +import io.realm.RealmViewHolder; public class MainActivity extends AppCompatActivity { @@ -54,27 +53,33 @@ public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); type = getIntent().getStringExtra("Type"); + if (type.equals("Grid")) { + setContentView(R.layout.activity_main_grid_layout); + } else { + setContentView(R.layout.activity_main_linear_layout); + } + realmRecyclerView = (RealmRecyclerView) findViewById(R.id.realm_recycler_view); + setTitle(getResources().getString(R.string.activity_layout_name, type)); resetRealm(); realm = Realm.getInstance(this); - realmRecyclerView = (RealmRecyclerView) findViewById(R.id.realm_recycler_view); - - if (type.equals("Grid")) { - GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2); - realmRecyclerView.setLayoutManager(gridLayoutManager); - } else { - LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); - linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); - realmRecyclerView.setLayoutManager(linearLayoutManager); + boolean isLoadMore = type.equals("LinearLoadMore"); + if (isLoadMore) { + realm.beginTransaction(); + for (int i = 0; i < 60; i++) { + QuoteModel quoteModel = realm.createObject(QuoteModel.class); + quoteModel.setId(i + 1); + quoteModel.setQuote(quotes.get((int) (quoteModel.getId() % quotes.size()))); + } + realm.commitTransaction(); } - + RealmResults quoteModels = - realm.where(QuoteModel.class).findAllSorted("id", false); + realm.where(QuoteModel.class).findAllSorted("id", isLoadMore ? true : false); quoteAdapter = new QuoteRecyclerViewAdapter(getBaseContext(), quoteModels, true, true); realmRecyclerView.setAdapter(quoteAdapter); @@ -86,6 +91,24 @@ public void onRefresh() { } } ); + + if (isLoadMore) { + realmRecyclerView.setOnLoadMoreListener( + new RealmRecyclerView.OnLoadMoreListener() { + @Override + public void onLoadMore(Object lastItem) { + if (lastItem instanceof QuoteModel) { + Toast.makeText( + MainActivity.this, + ((QuoteModel) lastItem).getId() + " ", + Toast.LENGTH_SHORT).show(); + } + asyncLoadMoreQuotes(); + } + } + ); + realmRecyclerView.enableShowLoadMore(); + } } @Override @@ -122,7 +145,7 @@ public QuoteRecyclerViewAdapter( super(context, realmResults, automaticUpdate, animateIdType); } - public class ViewHolder extends RecyclerView.ViewHolder { + public class ViewHolder extends RealmViewHolder { public FrameLayout container; public TextView quoteTextView; public ViewHolder(FrameLayout container) { @@ -133,15 +156,15 @@ public ViewHolder(FrameLayout container) { } @Override - public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + public ViewHolder onCreateRealmViewHolder(ViewGroup viewGroup, int viewType) { View v = inflater.inflate(R.layout.item_view, viewGroup, false); ViewHolder vh = new ViewHolder((FrameLayout) v); return vh; } @Override - public void onBindViewHolder(ViewHolder viewHolder, int i) { - final QuoteModel quoteModel = realmResults.get(i); + public void onBindRealmViewHolder(ViewHolder viewHolder, int position) { + final QuoteModel quoteModel = realmResults.get(position); viewHolder.quoteTextView.setOnClickListener( new View.OnClickListener() { @Override @@ -156,6 +179,11 @@ public void onClick(View v) { } viewHolder.quoteTextView.setText(quoteModel.getQuote()); } + + @Override + public ViewHolder convertViewHolder(RealmViewHolder viewHolder) { + return ViewHolder.class.cast(viewHolder); + } } private void asyncAddQuote() { @@ -223,6 +251,36 @@ protected void onPostExecute(Void aVoid) { remoteItem.execute(); } + private void asyncLoadMoreQuotes() { + AsyncTask remoteItem = new AsyncTask() { + @Override + protected Void doInBackground(Void... params) { + // Add some delay to the refresh/remove action. + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + Realm instance = Realm.getInstance(MainActivity.this); + instance.beginTransaction(); + for (int i = 0; i < 60; i++) { + QuoteModel quoteModel = instance.createObject(QuoteModel.class); + quoteModel.setId(i + 100); // That is to offset for primary key + quoteModel.setQuote(quotes.get((int) (quoteModel.getId() % quotes.size()))); + } + instance.commitTransaction(); + instance.close(); + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + realmRecyclerView.disableShowLoadMore(); + } + }; + remoteItem.execute(); + } + private void resetRealm() { RealmConfiguration realmConfig = new RealmConfiguration .Builder(this) diff --git a/example/app/src/main/java/co/moonmonkeylabs/realmrecyclerview/example/MainActivity2.java b/example/app/src/main/java/co/moonmonkeylabs/realmrecyclerview/example/MainActivity2.java new file mode 100644 index 0000000..8991929 --- /dev/null +++ b/example/app/src/main/java/co/moonmonkeylabs/realmrecyclerview/example/MainActivity2.java @@ -0,0 +1,174 @@ +package co.moonmonkeylabs.realmrecyclerview.example; + +import android.content.Context; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.TextView; + +import co.moonmonkeylabs.realmrecyclerview.RealmRecyclerView; +import co.moonmonkeylabs.realmrecyclerview.example.models.CountryModel; +import io.realm.Realm; +import io.realm.RealmBasedRecyclerViewAdapter; +import io.realm.RealmConfiguration; +import io.realm.RealmResults; +import io.realm.RealmViewHolder; + +public class MainActivity2 extends AppCompatActivity { + + private RealmRecyclerView realmRecyclerView; + private CountryRecyclerViewAdapter countryAdapter; + private Realm realm; + private String type; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main_linear_layout_headers); + + type = getIntent().getStringExtra("Type"); + setTitle(getResources().getString(R.string.activity_layout_name, type)); + + resetRealm(); + realm = Realm.getInstance(this); + + realmRecyclerView = (RealmRecyclerView) findViewById(R.id.realm_recycler_view); + + // Init Realm with n country names + final String[] countryNames = getResources().getStringArray(R.array.country_names); + realm.beginTransaction(); + for (int i = 0; i < countryNames.length; i++) { + CountryModel countryModel = new CountryModel(i, countryNames[i]); + realm.copyToRealm(countryModel); + } + realm.commitTransaction(); + + RealmResults countryModels = + realm.where(CountryModel.class).findAllSorted("name", true); + countryAdapter = new CountryRecyclerViewAdapter(getBaseContext(), countryModels); + realmRecyclerView.setAdapter(countryAdapter); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + realm.close(); + realm = null; + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_header_main, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int id = item.getItemId(); + if (id == R.id.add_b_tiem) { + asyncAddCountry("Belgium"); + return true; + } + return super.onOptionsItemSelected(item); + } + + public class CountryRecyclerViewAdapter extends RealmBasedRecyclerViewAdapter< + CountryModel, CountryRecyclerViewAdapter.ViewHolder> { + + public CountryRecyclerViewAdapter( + Context context, + RealmResults realmResults) { + super(context, realmResults, true, true, true, "name"); + } + + public class ViewHolder extends RealmViewHolder { + + public FrameLayout container; + + public TextView countryTextView; + + public ViewHolder(FrameLayout container) { + super(container); + this.container = container; + this.countryTextView = (TextView) container.findViewById(R.id.quote_text_view); + } + } + + @Override + public ViewHolder onCreateRealmViewHolder(ViewGroup viewGroup, int viewType) { + View v = inflater.inflate(R.layout.item_view, viewGroup, false); + return new ViewHolder((FrameLayout) v); + } + + @Override + public void onBindRealmViewHolder(ViewHolder viewHolder, int position) { + final CountryModel quoteModel = realmResults.get(rowWrappers.get(position).realmIndex); + viewHolder.countryTextView.setText(quoteModel.getName()); + viewHolder.countryTextView.setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View v) { + asyncRemoveCountry(quoteModel.getId()); + } + } + ); + } + + @Override + public ViewHolder convertViewHolder(RealmViewHolder viewHolder) { + return ViewHolder.class.cast(viewHolder); + } + } + + private void resetRealm() { + RealmConfiguration realmConfig = new RealmConfiguration + .Builder(this) + .deleteRealmIfMigrationNeeded() + .build(); + Realm.deleteRealm(realmConfig); + } + + private void asyncRemoveCountry(final long id) { + AsyncTask remoteItem = new AsyncTask() { + @Override + protected Void doInBackground(Void... params) { + Realm instance = Realm.getInstance(MainActivity2.this); + CountryModel countryModel = + instance.where(CountryModel.class).equalTo("id", id).findFirst(); + if (countryModel != null) { + instance.beginTransaction(); + countryModel.removeFromRealm(); + instance.commitTransaction(); + } + instance.close(); + return null; + } + }; + remoteItem.execute(); + } + + private void asyncAddCountry(final String name) { + AsyncTask remoteItem = new AsyncTask() { + @Override + protected Void doInBackground(Void... params) { + Realm instance = Realm.getInstance(MainActivity2.this); + instance.beginTransaction(); + CountryModel countryModel = + instance.where(CountryModel.class).equalTo("name", name).findFirst(); + if (countryModel == null) { + CountryModel newCountryModel = new CountryModel(1000, name); + instance.copyToRealm(newCountryModel); + instance.commitTransaction(); + } + instance.close(); + return null; + } + }; + remoteItem.execute(); + } +} diff --git a/example/app/src/main/java/co/moonmonkeylabs/realmrecyclerview/example/models/CountryModel.java b/example/app/src/main/java/co/moonmonkeylabs/realmrecyclerview/example/models/CountryModel.java new file mode 100644 index 0000000..a350677 --- /dev/null +++ b/example/app/src/main/java/co/moonmonkeylabs/realmrecyclerview/example/models/CountryModel.java @@ -0,0 +1,38 @@ +package co.moonmonkeylabs.realmrecyclerview.example.models; + +import io.realm.RealmObject; +import io.realm.annotations.PrimaryKey; + +/** + * The name model contains a name and a unique id. + */ +public class CountryModel extends RealmObject { + + @PrimaryKey + private long id; + private String name; + + public CountryModel() { + } + + public CountryModel(long id, String name) { + this.id = id; + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/example/app/src/main/java/co/moonmonkeylabs/realmrecyclerview/example/models/QuoteModel.java b/example/app/src/main/java/co/moonmonkeylabs/realmrecyclerview/example/models/QuoteModel.java index fa1bda1..ef611b9 100644 --- a/example/app/src/main/java/co/moonmonkeylabs/realmrecyclerview/example/models/QuoteModel.java +++ b/example/app/src/main/java/co/moonmonkeylabs/realmrecyclerview/example/models/QuoteModel.java @@ -1,18 +1,3 @@ -/* - * Copyright 2014 Realm Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ package co.moonmonkeylabs.realmrecyclerview.example.models; import io.realm.RealmObject; diff --git a/example/app/src/main/res/layout/activity_layout_selector.xml b/example/app/src/main/res/layout/activity_layout_selector.xml index 93adfcf..e14ba36 100644 --- a/example/app/src/main/res/layout/activity_layout_selector.xml +++ b/example/app/src/main/res/layout/activity_layout_selector.xml @@ -11,10 +11,24 @@ android:layout_margin="20dp" android:text="@string/linear_demo"/> +