java.lang.String cannot be cast to model.AtvLanguage - android

I'm using the library Hawk to persist data. I'm facing a problem with the data retrieved.
When I do the next code to check the value of an object stored, but sais it can't cast the value.
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to com.test.app.model.AtvLanguage
The code:
if(Hawk.contains("ATV_LANGUAGE")){
atvLanguage = (AtvLanguage)Hawk.get("ATV_LANGUAGE"); // Fail point
}else{
atvLanguage.setLanguageCodes("", getString(R.string.str_en));
}
The put method:
public void updateSelectedLanguage(String iso6391, String iso6392){
AtvLanguage atvLanguageTmp = new AtvLanguage(iso6391, iso6392);
Hawk.put("ATV_LANGUAGE", atvLanguageTmp);
}
AtvLanguage pojo:
public class AtvLanguage implements Serializable {
#SerializedName("iso6391")
#Expose
private String iso6391;
#SerializedName("iso6392")
#Expose
private String iso6392;
public AtvLanguage() {
}
public AtvLanguage(String iso6391, String iso6392) {
setLanguageCodes(iso6391, iso6392);
}
public String getIso6391() {
return iso6391;
}
public void setIso6391(String iso6391) {
this.iso6391 = iso6391;
}
public String getIso6392() {
return iso6392;
}
public void setIso6392(String iso6392) {
this.iso6392 = iso6392;
}
// ISO 639-2 is the language code with 3 chars, like ENG or SPA.
public void setLanguageCodes(String iso6391, String iso6392){
if(iso6391.isEmpty() && !iso6392.isEmpty()){
if(iso6392.equalsIgnoreCase("ENG"))
setIso6391("en");
else if(iso6392.equalsIgnoreCase("ESP"))
setIso6391("es");
setIso6392(iso6392);
}else if(!iso6391.isEmpty() && iso6392.isEmpty()){
if(iso6391.equalsIgnoreCase("en"))
setIso6392("ENG");
else if(iso6391.equalsIgnoreCase("es"))
setIso6392("ESP");
setIso6391(iso6391);
}
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AtvLanguage that = (AtvLanguage) o;
return new EqualsBuilder()
.append(getIso6391(), that.getIso6391())
.append(getIso6392(), that.getIso6392())
.isEquals();
}
#Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(getIso6391())
.append(getIso6392())
.toHashCode();
}
#Override
public String toString() {
return "AtvLanguage{" +
"iso6391='" + iso6391 + '\'' +
", iso6392='" + iso6392 + '\'' +
'}';
}
}

Related

Write unit test for function which return Observable

Problem Description
I'm trying to write test for simple class which is using Observable.
Test must be written for function buildUseCaseObservable which should first try to get data from network and if not succeed try to get from local database.
In the buildUseCaseObservable I'm using operator first which should filter data and return true if data is not null and empty.
If in the case of rest.getData() is called and data returned is not null I assume that first should return true and in that case data.getData() should not be called.
But in my case it seems that while testing function first is not called and both functions rest.getData() and data.getData() are always called.
Question
What I'm doing wrong and how I can correct test?
DataInteractor.java
#PerActivity
public class DataInteractor extends Interactor {
private RestService rest;
private DataService data;
#Inject
DataInteractor(RestService rest, DataService data) {
this.rest = rest;
this.data = data;
}
#Override
protected Observable buildUseCaseObservable() {
return Observable.concat(
rest.getData(),
data.getData())
.first(data -> data != null && !data.isEmpty());
}
}
DataService.java
public interface DataService {
Observable<List<IData>> getData();
}
RestService.java
public interface RestService {
#GET("data")
Observable<List<IData>> getData();
}
DataInteractorTest.java
public class DataInteractorTest {
private DataInteractor interactor;
#Mock private RestService mockedRest;
#Mock private DataService mockedData;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.interactor = new DataInteractor(mockedRest, mockedData);
}
#Test
public void firstDownloadDataFromNetwork() {
when(mockedRest.getData()).thenReturn(Observable.create(new Observable.OnSubscribe<List<IData>>() {
#Override
public void call(Subscriber<? super List<IData>> subscriber)
List<IData> data = new ArrayList<IData>() {{
add(new Data());
}};
subscriber.onNext(data);
subscriber.onCompleted();
}
}));
this.interactor.buildUseCaseObservable()
verify(this.mockedData, times(0)).getData();
}
}
Solution
Fortunately I found solution and right way of testing Rx stuff.
I found a nice article with very helpful class called RxAssertions with a small modification of class my tests start passing.
public class DataInteractorTest {
private DataInteractor interactor;
#Mock private RestService mockedRest;
#Mock private DataService mockedData;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.interactor = new DataInteractor(mockedRest, mockedData);
}
#Test
#SuppressWarnings("unchecked")
public void downloadDataFromNetwork_ignoreDataFromDatabase() {
when(mockedRest.getData()).thenReturn(this.getMockedData(4));
when(mockedData.getData()).thenReturn(this.getMockedData(8));
RxAssertions.subscribeAssertingThat(this.interactor.buildUseCaseObservable())
.completesSuccessfully()
.hasSize(4);
}
/**
* Helper function which return mocked data
*/
private Observable getMockedData(final int size) {
return Observable.create(new Observable.OnSubscribe<List<IData>>() {
#Override
public void call(Subscriber<? super List<IData>> subscriber) {
List<IData> data = new ArrayList<>();
for (int i = 0; i < size; ++i) {
data.add(new Data());
}
subscriber.onNext(data);
subscriber.onCompleted();
}
});
}
}
RxAsserations
public class RxAssertions {
public static <T> ObservableAssertions<T> subscribeAssertingThat(Observable<List<T>> observable) {
return new ObservableAssertions<>(observable);
}
public static class ObservableAssertions<T> {
private List<T> mResult;
private Throwable mError;
private boolean mCompleted;
public ObservableAssertions(Observable<List<T>> observable) {
mCompleted = false;
mResult = new ArrayList<>();
observable.subscribeOn(Schedulers.immediate())
.subscribe(new Observer<List<T>>() {
#Override
public void onCompleted() {
mCompleted = true;
}
#Override
public void onError(Throwable error) {
mError = error;
}
#Override
public void onNext(List<T> list) {
mResult.addAll(list);
}
});
}
public ObservableAssertions<T> completesSuccessfully() {
if (!mCompleted || mError != null) {
if (mError != null) mError.printStackTrace();
throw new AssertionFailedError("Observable has not completed successfully - cause: "
+ (mError != null ? mError : "onComplete not called"));
}
return this;
}
public ObservableAssertions<T> fails() {
if (mError == null) {
throw new AssertionFailedError("Observable has not failed");
}
return this;
}
public ObservableAssertions<T> failsWithError(Throwable throwable) {
fails();
if (!throwable.equals(mError)) {
throw new AssertionFailedError("Observable has failed with a different error," +
" expected is " + throwable + " but thrown was " + mError);
}
return this;
}
public ObservableAssertions<T> hasSize(int numItemsExpected) {
if (numItemsExpected != mResult.size()) {
throw new AssertionFailedError("Observable has emitted " + mResult.size()
+ " items but expected was " + numItemsExpected);
}
return this;
}
#SafeVarargs
public final ObservableAssertions<T> emits(T... itemsExpected) {
completesSuccessfully();
assertEmittedEquals(itemsExpected);
return this;
}
#SuppressWarnings("unchecked")
public ObservableAssertions<T> emits(Collection<T> itemsExpected) {
completesSuccessfully();
assertEmittedEquals((T[]) itemsExpected.toArray());
return this;
}
public ObservableAssertions<T> emitsNothing() {
completesSuccessfully();
if (mResult.size() > 0) {
throw new AssertionFailedError("Observable has emitted " + mResult.size() + " items");
}
return this;
}
private void assertEmittedEquals(T[] itemsExpected) {
hasSize(itemsExpected.length);
for (int i = 0; i < itemsExpected.length; i++) {
T expected = itemsExpected[i];
T actual = mResult.get(i);
if (!expected.equals(actual)) {
throw new AssertionFailedError("Emitted item in position " + i + " does not match," +
" expected " + expected + " actual " + actual);
}
}
}
}
}

java.lang.RuntimeException: Parcel: unable to marshal value com.package.NutritionInfo#84055e1

In two situations, only one of them gives me this unique error. I pretty much followed the Android Tutorial character for character, and for some reason it only works in certain areas.
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_TEXT, getSharedNutritionText(mMultiSelector.getSelectedPositions()));
shareIntent.setType("text/plain");
startActivity(shareIntent);
Gives the following error:
12-13 02:10:07.838 8261-8261/com.example E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.skylan.homeworkpro, PID: 8261
java.lang.RuntimeException: Parcel: unable to marshal value com.example.NutritionInfo#2d54b4d1
at android.os.Parcel.writeValue(Parcel.java:1343)
at android.os.Parcel.writeList(Parcel.java:717)
at android.os.Parcel.writeValue(Parcel.java:1290)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:644)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1313)
at android.os.Bundle.writeToParcel(Bundle.java:1034)
at android.os.Parcel.writeBundle(Parcel.java:669)
at android.app.FragmentState.writeToParcel(Fragment.java:138)
at android.os.Parcel.writeTypedArray(Parcel.java:1197)
at android.app.FragmentManagerState.writeToParcel(FragmentManager.java:376)
at android.os.Parcel.writeParcelable(Parcel.java:1363)
at android.os.Parcel.writeValue(Parcel.java:1268)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:644)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1313)
at android.os.Bundle.writeToParcel(Bundle.java:1034)
at android.os.Parcel.writeBundle(Parcel.java:669)
at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:2925)
at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3299)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Whereas in another one of my (almost) identical fragments, I have the following code:
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_TEXT, getSharedLabelText(mMultiSelector.getSelectedPositions()));
shareIntent.setType("text/plain");
startActivity(shareIntent);
Here's my NutritionInfo Class
public class NutritionInfo extends SugarRecord<NutritionInfo> {
public String nutritionName;
public String nutritionHeaderTitle;
public int nutritionCalories;
public boolean nutritionArchived;
public boolean nutritionChecked;
public NutritionInfo () {}
public NutritionInfo (String name, String headerTitle, int cal, boolean isArchived, boolean isChecked) {
nutritionName = name;
nutritionHeaderTitle = headerTitle;
nutritionCalories = cal;
nutritionArchived = isArchived;
nutritionChecked = isChecked;
}
}
Here's my Nutrition getter:
public class NutritionDisplayFragment extends BaseFragment implements ActionMode.Callback {
private String getSharedNutritionText(List<Integer> positions) {
String shareText;
if (positions.equals(null)) {
shareText = "";
} else {
shareText = "Food and carbs:\n";
for (int go = 0; go < positions.size(); go++) {
shareText = shareText +
nutritionList.get(go).nutritionTitle + " - \t" +
nutritionList.get(go).nutritionCarbs + "\n";
}
}
return shareText;
} ( . . . )
}
vs my Label getter:
public class LabelManagerFragment extends BaseFragment implements ActionMode.Callback {
private String getSharedLabelText(List<Integer> positions) {
String shareText = "";
if (positions.equals(null)) {
shareText = "";
} else {
for (int go = 0; go < positions.size(); go++) {
shareText = shareText +
labelList.get(go).labelName + "\t" +
labelList.get(go).labelYear + "\n";
}
}
return shareText;
} ( . . . )
}
And this gives no runtime error. Both get() methods return a simple string. Why does the first error complain about "com.package.NutritionInfo#84055e1", which isn't even the type of data being shared, as un-marshal-able and the other shares the string without a hitch?
For further clarity: I tried hardcoding "hello world" in for where the method is (the method that usually returns a simple String), and had the same issue.
Implement the Parcelable interface like follows:
public class NutritionInfo extends SugarRecord<NutritionInfo> implements Parcelable {
public String nutritionName;
public String nutritionHeaderTitle;
public int nutritionCalories;
public boolean nutritionArchived;
public boolean nutritionChecked;
public NutritionInfo() {
}
public NutritionInfo(String name, String headerTitle, int cal, boolean isArchived, boolean isChecked) {
nutritionName = name;
nutritionHeaderTitle = headerTitle;
nutritionCalories = cal;
nutritionArchived = isArchived;
nutritionChecked = isChecked;
}
protected NutritionInfo(Parcel in) {
nutritionName = (String) in.readValue(null);
nutritionHeaderTitle = (String) in.readValue(null);
nutritionCalories = in.readInt();
nutritionArchived = in.readByte() != 0;
nutritionChecked = in.readByte() != 0;
}
public static final Creator<NutritionInfo> CREATOR = new Creator<NutritionInfo>() {
#Override
public NutritionInfo createFromParcel(Parcel in) {
return new NutritionInfo(in);
}
#Override
public NutritionInfo[] newArray(int size) {
return new NutritionInfo[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(nutritionName);
dest.writeValue(nutritionHeaderTitle);
dest.writeInt(nutritionCalories);
dest.writeByte((byte) (nutritionArchived ? 1 : 0));
dest.writeByte((byte) (nutritionChecked ? 1 : 0));
}
}
Do the same for your sugar record. And if the super class implements Parcelable you do not need to declare again in NutritionInfo, only implement the stuff.

ArrayList.indexOf() is not recognizing Objects

I have a ParseObject subclass , but everytime I want to get index of it it returns 0 so mListSectionPos returns an array of zero's (hachCode and equals methd implemented thanks to Apache Commons Utils).
It should be String.valueOf(mListItems.indexOf(beer_section)), but instead I'm using mListSectionPos.add(mListItems.indexOf(current_item) - 1); because it's working (more or less). Sometimes it cracks on getCurrentSectionPosition() that also works on indexOf() method.
So my question is: why indexOf() always return 0 in this piece of code?
It's based on https://github.com/bhavyahmehta/ListviewFilter - just adapted for ParseObject lists. Code below is my adaptation of his MainActivity.java that can be found here:
#Override
protected Void doInBackground(ArrayList<PiwoSubclass>... params) {
mListItems.clear();
mListSectionPos.clear();
ArrayList<PiwoSubclass> items = params[0];
if(mItems != null) {
if (mItems.size() > 0) {
String prev_section = "";
for (PiwoSubclass current_item : items) {
if (isCancelled()) break;
String current_section = current_item.getBeerName().substring(0, 1).toUpperCase(Locale.getDefault());
if (!prev_section.equals(current_section)) {
PiwoSubclass beer_section = null;
beer_section = new PiwoSubclass();
beer_section.setBeerName(current_section);
Log.i("ASD-current", beer_section.getBeerName());
mListItems.add(beer_section);
mListItems.add(current_item);
// array list of section positions
mListSectionPos.add(mListItems.indexOf(current_item) - 1); // that want works although it's way around
// TODO why is that error?
Log.i("ASD-listSectionSize", String.valueOf(mListItems.indexOf(beer_section)));
prev_section = current_section;
} else {
mListItems.add(current_item);
}
}
}
}
return null;
}
PiwoSubclass
public class PiwoSubclass extends ParseObject {
private String objectIdP;
private String marka;
private String marka_lowercase;
public PiwoSubclass() {
}
public String getObjectIdfromParse() {
return this.getObjectId();
}
public String getMarka(){
return this.getString("marka");
}
public String getBrewery(){
return this.getString("brewery");
}
public String getBeerName(){
return this.getString("beer_name");
}
public String getMarka_lowercase() {
return this.getString("marka_lowercase");
}
public void setMarka(String value){
put("marka", value);
}
public void setBeerName(String value){
put("beer_name", value);
}
public void setMarka_lowercase(String value){
put("marka_lowercase", value);
}
#Override
public int hashCode() {
return new HashCodeBuilder(17, 31) // two randomly chosen prime numbers
// if deriving: appendSuper(super.hashCode()).
.append(getObjectIdfromParse())
.toHashCode();
}
#Override
public boolean equals(Object obj) {
//return super.equals(obj);
if (!(obj instanceof PiwoSubclass))
return false;
if (obj == this)
return true;
marka_lowercase = getMarka_lowercase();
PiwoSubclass rhs = (PiwoSubclass) obj;
//Log.i("ASD-subclass", marka + "/" + rhs.getMarka());
return new EqualsBuilder()
// if deriving: appendSuper(super.equals(obj)).
.append(marka_lowercase, rhs.getMarka_lowercase())
.isEquals();
}
Now I have IndexOutOfBounds exception from PinnedHeaderAdapter:
public int getCurrentSectionPosition(int position) {
//String listChar = mListItems.get(position).getBeerName().substring(0, 1).toUpperCase(Locale.getDefault());
PiwoSubclass ps = mListItems.get(position); // TODO errorrrrrrrrr
return mListItems.indexOf(ps);
}
First, you check for mItems
if(mItems != null) {
if (mItems.size() > 0) {
but then you work with items
for (PiwoSubclass current_item : items) {
/* ... */
}
and ignore mItems for the rest of the method. I don't see any connection between these two.
It seems indexOf() doesn't return 0 but 1, otherwise you would get an ArrayList full of -1s
mListSectionPos.add(mListItems.indexOf(current_item) - 1);
I guess, somehow you always check for the first current_item, which is the second element in mListItems. If you would check for the beer_section - as it does for current_section in the original code - the code would work as expected.
After looking into ArrayList.indexOf(), the most likely reason is your PiwoSubclass.equals() method compares always equal to the first non-section element, because it hasn't set a beer name or some similar condition.
So, fixing the equals method might work as well.

Changing Channel on Google TV

I am trying to write a simple app for Google TV which generates a random number from 1-10 then randomly selects a channel (501-510) and loads it.
I have tried the official google documentation but the official sample project doesnt compile. I have also read Is the GTV Channel Listing/Change API/Sample is broken on LG G2? and tried to adapt this into the google version however the app crashes on loading.
Im sure this must be a simple fix. I do not need to get information about the channel or search for them using the tutorial at https://developers.google.com/tv/android/docs/gtv_provider.
Any help greatly appreciated.
The access to the providers have changed if you use the code below things should improve.
Permissions:
<uses-permission android:name="com.google.android.tv.permission.READ_CHANNELS"/>
<uses-permission android:name="com.google.android.tv.mediadevices.permission.READ_STREAMS"/>
code:
public abstract class ChannelList {
private static ChannelList mCL=null;
public abstract String getPROVIDER_URI();
public abstract String getCALL_SIGN_COLUMN();
public abstract String getURI_COLUMN();
public abstract String getNUMBER_COLUMN();
public abstract String getNAME_COLUMN();
public static ChannelList getChannelList() {
if (mCL != null)
return mCL;
int mGtvLibraryVersion = 0;
try {
Class<?> cl = Class.forName("com.google.android.tv.Version");
mGtvLibraryVersion = cl.getField("GTV_SDK_INT").getInt(null);
} catch (Exception ex) {}
Log.d("Resolution Test", "Version " + mGtvLibraryVersion);
mCL= mGtvLibraryVersion > 0 ? new Version3ChannelList(): new Version2ChannelList();
return mCL;
}
/**
* Use the getChannelList factory to obtain an instance of a subclass of
* ChannelList
*/
private ChannelList() {
}
#Override
public String toString() {
return "SDK Provider: " + getPROVIDER_URI() + "\n" +
"Columns: " + getCALL_SIGN_COLUMN() + " " + getURI_COLUMN() + " " + getNUMBER_COLUMN() + " "
+ getNAME_COLUMN();
}
public static final class Version2ChannelList extends ChannelList {
#Override
public String getPROVIDER_URI() {
return "content://com.google.android.tv.provider/channel_listing";
}
#Override
public String getCALL_SIGN_COLUMN() {
return "callsign";
}
#Override
public String getURI_COLUMN() {
return "channel_uri";
}
#Override
public String getNUMBER_COLUMN() {
return "channel_number";
}
#Override
public String getNAME_COLUMN() {
return "channel_name";
}
}
public static final class Version3ChannelList extends ChannelList {
#Override
public String getPROVIDER_URI() {
return "content://com.google.tv.mediadevicesapp.MediaDevicesProvider/channel_list";
}
#Override
public String getCALL_SIGN_COLUMN() {
return "subName";
}
#Override
public String getURI_COLUMN() {
return "url";
}
#Override
public String getNUMBER_COLUMN() {
return "channelNumber";
}
#Override
public String getNAME_COLUMN() {
return "name";
}
}

How to apply multiple Filters on an Adapter?

I got a listView with and a search field that calls my Adapter's getFilter().filter(keyword) func.
It is working very nice, but i would like to add an other filter that searches in different tags of my listViews's objects.
So i need two filters for my Adapter, whats the best solution for this?
Thanks,
I suppose that you implemented the filter yourself. As you cant get two filters you could have a field in the filter that defines what kind of filtering should by applied ( you could use multiple filters in your filter).
Set you field of the filter to the value you want before using the filter.
Or:
Use the keyword to choose the filter to apply. Add on the beginning of the keyword some characters which define the filter to apply. With String.beginsWith() you can check which type of filtering has to by applied. This has to be done in the Filter itself. The caller of the getFilter.filter(keyword) has to know what characters have to by added in front of the string.
Apply Multiple Filter in Listview and also use the multi sorting in ListView, try this link:
https://github.com/apurv3039/filter_listview/tree/master
I had a similar need and I've written for myself. The filter are combined with AND operator. Keep it as simple as possible. Not claiming it is perfect but it works for me. You can change according to your need.
The ItemModel
public class ItemModel {
public int ID;
public int rating;
public float avg;
public String name;
public String shortDesc;
public boolean read;
}
And the parser.java
/**
* This class is designed to be simple for parsing a filter of the form
* "object field name: variable type: operator: value"
*
* "ID:int:>:20";"name:string:=:20"
* Where ';' means AND, however this is not parsed here.
* If you need different logic, use the results.O
*
* Multiple filters seperated by ';'
*/
public class Parser {
private static final String TAG = "Parser";
public static boolean isPassingTheFiler(String filter, String field, String val) {
String[] mGroups = parseMainGroups(filter);
for (String mGroup : mGroups) {
Log.e(TAG,"Working on the main Group " +mGroup );
String[] subCommand = parseSubCommand(mGroup);
if ( field.equals(subCommand[0])) {
if (!processCommand(subCommand, val)) {
return false;
}
}
}
return true;
}
/**
* parses that data assuming they are all sperated by `;`
*/
public static String[] parseMainGroups(CharSequence commands) {
String buffer = commands.toString();
String parts[] = buffer.split(";");
return parts;
}
public static String[] parseSubCommand(String subCommand) {
//remove the double quotes.
String buffer = removeDoubleQuotes(subCommand.toString());
String parts[] = buffer.split(":");
return parts;
}
public static String removeDoubleQuotes(String quotedString) {
if ((quotedString.charAt(0) == '\"') && (quotedString.charAt(quotedString.length() - 1) == '\"')) {
return quotedString.substring(1, quotedString.length() - 1);
} else {
Log.e(TAG, quotedString + " doesn't contained in double quotes!\nReturned empty string!!!");
return "";
}
}
public static boolean processCommand(String[] subCommand, String val) {
switch (subCommand[1]) {
case "int":
Log.e("TAG","\tint Filer");
return intStatement(subCommand, val);
case "float":
Log.e("TAG","\tfloat Filer");
return floatStatement(subCommand, val);
case "string":
Log.e("TAG","\tString Filer");
return stringStatement(subCommand, val);
default:
return false;
}
}
/**
* Evaluate the Int statement's correctness with the given INT value
*/
public static boolean intStatement(String[] subCommand, String cVal) {
String operString = subCommand[2];
int iVal;
int val;
try {
iVal = Integer.parseInt(subCommand[3]);
val = Integer.parseInt(cVal);
} catch (NumberFormatException e) {
return false;
}
switch (operString) {
case "=":
return val == iVal;
case "<":
return val < iVal;
case ">":
return val > iVal;
case "<=":
return val <= iVal;
case ">=":
return val >= iVal;
case "!=":
return val != iVal;
case "s" :
//digit search as string. We look into string from that we already have
return cVal.contains(subCommand[3]);
default:
Log.e("Parser", "invalid Integer Operation");
return false;
}
}
public static boolean floatStatement(String[] subCommand, String cVal) {
String operString = subCommand[2];
float iVal;
float val;
try {
iVal = Float.parseFloat(subCommand[3]);
val = Float.parseFloat(cVal);
} catch (NumberFormatException e) {
return false;
}
switch (operString) {
case "=":
return val == iVal;
case "<":
return val < iVal;
case ">":
return val > iVal;
case "<=":
return val <= iVal;
case ">=":
return val >= iVal;
case "!=":
return val != iVal;
case "s" :
//digit search as string. We look into string from that we already have
return cVal.contains(subCommand[3]);
default:
Log.e("Parser", "invalid Integer Operation");
return false;
}
}
public static boolean stringStatement(String[] subCommand, String val) {
String operString = subCommand[2];
switch (operString) {
case "=":
//equality
return val.equals(subCommand[3]);
case "<":
//substring
return val.contains(subCommand[3]);
case "sw":
//prefix
return val.startsWith(subCommand[3]);
case "ew":
//postfix
return val.endsWith(subCommand[3]);
default:
Log.e("Parser", "invalid Integer Operation");
return false;
}
}
}
The private filter class in the adapter.
private class ItemFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
String charString = constraint.toString();
String[] parts;
FilterResults filterResults = new FilterResults();
if (charString.isEmpty()) {
filterResults.values = new ArrayList<>(itemList);
} else {
//Parse the main group
parts = parseMainGroups(charString);
if (parts.length < 1) {
filterResults.values = new ArrayList<>(itemList);
} else {
List<ItemModel> filteredList = new ArrayList<>();
for (ItemModel row : itemList) {
if ( !isPassingTheFiler(charString,"ID",""+row.ID)) {
continue;
} else {
Log.e("Filter", "passed on ID" + row.ID);
}
if ( !isPassingTheFiler(charString,"name",""+row.name)) {
continue;
} else {
Log.e("Filter", "passed on name" + row.name);
}
// passed every test asked. If empty they returned true!
filteredList.add(row);
}
filterResults.values = new ArrayList<>(filteredList);
}
}
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
updateList((List<ItemModel>) results.values);
}
}
And the updateList member funtion for the adapter
public void updateList(List<ItemModel> newList) {
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new ItemDiffUtilCallback(newList, itemListFiltered));
itemListFiltered.clear();
itemListFiltered.addAll(newList);
diffResult.dispatchUpdatesTo(this);
Log.e("TAG", "updated with dispatch");
}
And the difutils that helps the good animation
public class ItemDiffUtilCallback extends DiffUtil.Callback {
private List<ItemModel> oldList;
private List<ItemModel> newList;
public ItemDiffUtilCallback(List<ItemModel> newList, List<ItemModel> oldList) {
this.newList = newList;
this.oldList = oldList;
}
#Override
public int getOldListSize() {
return oldList.size();
}
#Override
public int getNewListSize() {
return newList.size();
}
#Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldList.get(oldItemPosition).ID == newList.get(newItemPosition).ID;
}
#Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldList.get(oldItemPosition).equals(newList.get(newItemPosition));
}
#Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
return super.getChangePayload(oldItemPosition, newItemPosition);
}

Categories

Resources