I have to implement the multiple search query, how to achieve it , I know the basic idea of filtering the text with the search view but not getting the idea how to search with multiple string ,I am attaching the snapshot show it will make you feel better to get an idea.
I am loading the data from the webserver.
TruckInfo columns are:
Name of the truck
Total capacity (is the capacity of the truck)
Status Free/Busy (is the status of the truck which is currently all truck is free)
Free location (is the where truck is going to free).
Now as in snapshot second i have to filter this data , I had searched in the capacity column --> 10 tonnes to 45 tonnes, status is--> free , free location is -->CV , from 7wed2016 to 20 Fri 2016 and then i hit search button .
Expected output should not show any result because:
10 tonnes to 45 tonnes there is 2 truck ..which is right. as data coming from server
status of both the truck is free, which is right
Free location is CV that I searched, but as you can see both truck have free location mumbais, chandigarh, so this condition is false so overall search should show no data
My Try:
filter_search.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.e("filter_search","filter_search");
Localytics.tagEvent("Trucks Search Screen");
if(frmcap.getText().toString().length()==0){
frmcap_val=0;
cap_bool=1;
}
else
{
frmcap_val=Integer.parseInt(frmcap.getText().toString());
cap_bool=0;
}
if(tocap.getText().toString().length()==0) {
tocap_val=0;
cap_bool = 1;
}
else {
tocap_val=Integer.parseInt(tocap.getText().toString());
cap_bool=0;
}
if(from_loc_text.getText().length()==0)
loc_bool=1;
else
loc_bool=0;
if(frm_date_value.length()==0 || to_date_value.length()==0)
date_bool=1;
else
date_bool=0;
if(free.isChecked())
status_value="true";
if(busy.isChecked())
status_value="false";
if(any.isChecked())
status_value="any";
if(!any.isChecked()&&!free.isChecked()&&!busy.isChecked()){
Log.e("##inside","inside");
status_value="-default value";
}
if(!any.isChecked()&&!free.isChecked()&&!busy.isChecked())
status_bool=1;
if(search.getText().length()==0)
loc_search_info=1;
else
loc_search_info=0;
try {
if(status_value!=null && status_value.length()>0 && !status_value.equalsIgnoreCase("any")){
truckadapter.advanceSearchFilter(status_value,"checkBox");
list_mytrucks.setVisibility(View.VISIBLE);
}else if(status_value!=null && status_value.equalsIgnoreCase("any")){
list_mytrucks.setVisibility(View.VISIBLE);
}else if(frmcap.getText().toString()!=null && frmcap.getText().toString().length()>0){
truckadapter.advanceSearchFilter(frmcap_val+"","capacity");
list_mytrucks.setVisibility(View.VISIBLE);
}else if(tocap.getText().toString()!=null && tocap.getText().toString().length()>0){
truckadapter.advanceSearchFilter(tocap_val+"","capacity");
list_mytrucks.setVisibility(View.VISIBLE);
}else if(current_location.getText().length()>=0){
truckadapter.advanceSearchFilter(current_location.getText().toString(),"freeLocation");
list_mytrucks.setVisibility(View.VISIBLE);
}else if(fromdt.getText().length()>=0){
truckadapter.advanceSearchFilter(current_location.getText().toString(),"dateStamp");
list_mytrucks.setVisibility(View.VISIBLE);
}else if(todt.getText().length()>=0){
truckadapter.advanceSearchFilter(current_location.getText().toString(),"dateStamp");
list_mytrucks.setVisibility(View.VISIBLE);
}
view_advance_search.setVisibility(View.GONE);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
Here is searchFiletring in getViewMethod:
public void advanceSearchFilter(String constraint,String tag) throws JSONException {
items.clear();
if(constraint.isEmpty()){
items.addAll(advanceSearchArrayList);
} else{
constraint = constraint.toUpperCase();
for(int i=0;i<advanceSearchArrayList.size();i++){
JSONObject jsonData = new JSONObject(String.valueOf(advanceSearchArrayList.get(i).getVehicle()));
if(tag.equalsIgnoreCase("capacity")){
int truckCapacity=Integer.parseInt(constraint);
if(Integer.parseInt(jsonData.getJSONObject("type").getString("capacity").toUpperCase())>=truckCapacity){
items.add(advanceSearchArrayList.get(i));
}
}
if(tag.equalsIgnoreCase("checkBox")){
if(advanceSearchArrayList.get(i).getFree().toUpperCase().contains(constraint)){
items.add(advanceSearchArrayList.get(i));
}
}
if(tag.equalsIgnoreCase("freeLocation")){
if(advanceSearchArrayList.get(i).getFree().toUpperCase().equalsIgnoreCase("true")){
Log.e("getFree_loc",""+advanceSearchArrayList.get(i).getFree_loc());
if(advanceSearchArrayList.get(i).getFree_loc().toUpperCase().contains(constraint)){
items.add(advanceSearchArrayList.get(i));
}
}
}
if(tag.equalsIgnoreCase("dateStamp")){
SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy");
Date date = null;
try {
date = formatter.parse(constraint);
} catch (ParseException e) {
e.printStackTrace();
}
try {
if(formatter.parse(advanceSearchArrayList.get(i).getFree().toUpperCase()).before(date) ){
items.add(advanceSearchArrayList.get(i));
}
} catch (ParseException e) {
e.printStackTrace();
}
}
}
}
notifyDataSetChanged();
}
You need to still explicitly compare each filter to property of each object to see if it matches or not.
Just an idea for flow:
Make a class for filter input. when user clicks search button, assign all filter values to that class.
Make a method inside model class, that returns true if any of the filter value matches. That takes filter class object as argument.
Now when user clicks search button, iterate over each object in array. Call this method. If it returns true, add this object in new filter array.
Use that filter array to show search results.
Example Code
///////// Filter class
class FilterTrucks {
String location;
int capacityStart;
int capacityEnd;
Arraylist<String> availability;
}
////// You model class
class Mytrucks {
String name;
String location;
int capacity;
String availability;
boolean matchFilter(FilterTrucks filter) {
boolean locationMatch = filterMatchesLocation(filter);
if(locationMatch)
return true;
boolean matchCapacity = filterMatchesCapacity(filter);
if(matchCapacity)
return true;
return false;
}
boolean filterMatchesLocation(FilterTrucks filter) {
return location.contains(filter.location);
}
boolean filterMatchesCapacity(FilterTrucks filter) {
return (capacity >= filter.capacityStart || capacity <= filter.capacityEnd)
}
////////// Your activity
Arraylist<Mytrucks> filterArray = new Arraylist<>();
filter_search.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//create filter object from user selected fields
FilterTrucks filter = new FilterTrucks();
filter.location = txtLocation.getText().toString(); //for example
for(Mytrucks truck : arraylist) {
if(truck.matchFilter(filter))
filterArray.add(truck);
}
}
});
//use filter array to populate recycler view
Hope this helps!
Related
I want to update key values when it removed, so I wrote codes below. These codes are in the Checkbox listener.
What I did first :
if(isChecked) {
Long size = dataSnapshot.child("Bookmark").getChildrenCount();
ref_h.child(userUid).child("Bookmark").child(Long.toString(size + 1)).setValue(diningUid);
} else {
for (int i = 1; i <= dataSnapshot.child("Bookmark").getChildrenCount(); i++) {
if (dataSnapshot.child("Bookmark").child(Integer.toString(i)).getValue().toString().equals(diningUid)) {
dataSnapshot.child("Bookmark").child(Integer.toString(i)).getRef().removeValue();
isRemoved = true;
}
if(isRemoved) {
if(i != dataSnapshot.child("Bookmark").getChildrenCount()){
String newDiningUid;
newDiningUid = dataSnapshot.child("Bookmark").child(Integer.toString(i + 1)).getValue().toString();
Log.d("newUID", newDiningUid);
ref_h.child(userUid).child("Bookmark").child(Integer.toString(i)).setValue(newDiningUid);
} else {
dataSnapshot.child("Bookmark").child(Integer.toString(i)).getRef().removeValue();
}
}
}
}
But when the Checkbox status changes rapidly, key values are messed up.
like this
data structure 2
Then I fixed the code with try-catch phrase.
if(isChecked) {//if not checked before listener runs, add to bookmark
Long size = dataSnapshot.child("Bookmark").getChildrenCount();
ref_h.child(userUid).child("Bookmark").child(Long.toString(size + 1)).setValue(diningUid);
} else {//if checked before listener runs, remove from bookmark
for (int i = 1; i <= dataSnapshot.child("Bookmark").getChildrenCount(); i++) {
try {
if (dataSnapshot.child("Bookmark").child(Integer.toString(i)).getValue().toString().equals(diningUid)) {
dataSnapshot.child("Bookmark").child(Integer.toString(i)).getRef().removeValue();
isRemoved = true;
}
} catch (NullPointerException e) {
if (dataSnapshot.child("Bookmark").child(Integer.toString(i + 1)).getValue().toString().equals(diningUid)) {
dataSnapshot.child("Bookmark").child(Integer.toString(i + 1)).getRef().removeValue();
isRemoved = true;
}
}
if(isRemoved) {
//update afterward value's index
if(i != dataSnapshot.child("Bookmark").getChildrenCount()){
String newDiningUid;
newDiningUid = dataSnapshot.child("Bookmark").child(Integer.toString(i + 1)).getValue().toString();
ref_h.child(userUid).child("Bookmark").child(Integer.toString(i)).setValue(newDiningUid);
} else {//remove last value
try {
dataSnapshot.child("Bookmark").child(Integer.toString(i)).getRef().removeValue();
} catch (NullPointerException e) {
dataSnapshot.child("Bookmark").child(Integer.toString(i + 1)).getRef().removeValue();
}
}
}
}
}
But I don't think I solved this problem.
How can I update key values properly?
or do I need to add a delay to Checkbox?
or change the data structure?
The best solution is to not use sequential numeric keys, but rely on Firebase's push IDs. For reasons on why this is a better approach and how they work, see these classic Firebase blog posts:
Best Practices: Arrays in Firebase
The 2^120 Ways to Ensure Unique Identifiers
If you insist on using array-like keys, you will have to use a transaction on the entire bookmark node to determine the next index. This is the only way to prevent the race condition that you now encounter when the array contents frequently change.
When I bind data in Adapter, I use Model to do this.
class ModelA{
ModelB b;
......
geters and setters
}
class ModelB{
ModelC c;
......
geters and setters
}
class ModelC{
String name;
......
geters and setters
}
when I want to use name, I need to do this:
bindData(ModelA a) {
String name = a.getModelB().getModelC().getName();
mTextView.setText(name);
}
but model may be null,so I added this:
bindData(ModelA a) {
if(a != null && a.getModelB() != null
&& a.getModelC() != null
&&!TextUtils.isempty(a.getModelB().getModelC().getName())) {
String name = a.getModelB().getModelC().getName();
mTextView.setText(name);
}
}
However I think use try catch may be easier,so I changed this:
bindData(ModelA a) {
try{
String name = a.getModelB().getModelC().getName();
mTextView.setText(name);
}catch (NullPointerException e) {
......
}
}
Is there a better way to judge model is null? if not, "if" and "try catch" which is better?
In my case, I checked if model is null in advance and I don't check variable from getter(). Because if it's null, we don't need to render views. (It's one of the reason why I want to move Java to Kotlin because I don't like checking NULL)
initViews() {
// handle your default data for Views
}
renderViews(ModelA a) {
ModelB modelB = a.getModelB;
if (modelB == null {
return;
}
// bind data of ModelB to Views
ModelC modelC = modelB.getModelC();
if (modelC == null) {
return;
}
// bind data of ModelC to Views
String name = modelC.getName();
mTextView.setText(name);
}
How to sort my list through Rx function, My list contain three type of different source then I want to display my list sorted using date, how to apply that using RxAndroid?
subscriptions.add(complaintsAPI.getComplaintsAPI(userDetails.getUsername())
.compose(ReactiveUtils.applySchedulers())
.map(list -> {
List<ComplaintsRowModel> rowModel = new ArrayList<>();
for (Complaint complaint : list.getComplaints()) {
rowModel.add(new ComplaintsRowModel(complaint.getDisputeNo(),
complaint.getOpenDate(), complaint.getArea(), complaint.getStatus()));
model.complaintsList.put(complaint.getDisputeNo(), complaint);
}
for (OnlineRequest onlineRequest : list.getOnlineRequests()) {
rowModel.add(new ComplaintsRowModel(onlineRequest.getRequestNo(), onlineRequest.getOpenDate(),
onlineRequest.getArea(), onlineRequest.getStatus()));
model.complaintsList.put(onlineRequest.getRequestNo(), onlineRequest);
}
for (LlTickets llTickets : list.getLlTickets()) {
rowModel.add(new ComplaintsRowModel(llTickets.getTicketNo(), llTickets.getOpenDate(),
llTickets.getType(), llTickets.getStatus()));
model.complaintsList.put(llTickets.getTicketNo(), llTickets);
}
return rowModel;}
).toSortedList(){
//how to sort here
}).subscribe(new RequestSubscriber<List<ComplaintsRowModel>>(view.getContext(), view.progressView) {
#Override
public void onFailure(RequestException requestException) {
view.showError(requestException);
}
#Override
public void onNoData() {
super.onNoData();
isAllDataLoaded = true;
view.noDataFound();
model.setNoDataFound(true);
}
#Override
public void onNext(List<ComplaintsRowModel> complaintsRowModels) {
isAllDataLoaded = true;
model.setRowModel(complaintsRowModels);
view.buildList(complaintsRowModels);
}
}));
I think in toSortedList() can I sort my list but I don't know the way to apply that.
The toSortedList operator would only work on Observable<ComplaintRowModel> while what you have is Observable<List<ComplaintRowModel>>. So first you have to transform your observable with
flatMapIterable(complaintRowModels -> complaintRowModels)
to map it to an observable of the list elements. Then you can apply the sorting something like
toSortedList((complaintRowModel, complaintRowModel2) -> {
Date date = complaintRowModel.getDate();
Date date2 = complaintRowModel2.getDate();
// comparing dates is very much dependent on your implementation
if (date <before> date2) {
return -1;
} else if (date <equal> date2) {
return 0;
} else {
return 1;
}
})
Then you get an observable of sorted list.
As per you don't want to provide specific information about your problem, there is generic answer.
When data object which need to be sorted implements Comparable or it's primitive type.
Observable.just(3, 2, 1)
.toSortedList()
.subscribe(list -> System.out.print(Arrays.toString(list.toArray())));
[1, 2, 3]
When data object which need to be sorted doesn't implement Comparable or implements it, but you need to specify how you'd like to sort data.
That sample illustrate how to sort list of objects by val field in descended order.
static class ToSort {
Integer val;
public ToSort(Integer val) {
this.val = val;
}
#Override
public String toString() {
return "ToSort{" +
"val=" + val +
'}';
}
}
public static void main(String[] args) {
Observable.just(new ToSort(1), new ToSort(2), new ToSort(3))
.toSortedList((o1, o2) -> (-1) * o1.val.compareTo(o2.val))
.subscribe(list -> System.out.print(Arrays.toString(list.toArray())));
}
[ToSort{val=3}, ToSort{val=2}, ToSort{val=1}]
Different approach to replce the
// comparing dates is very much dependent on your implementation
if (date <before> date2) {
return -1;
} else if (date <equal> date2) {
return 0;
} else {
return 1;
}
Using a static import java.util.Comparator.comparing;
you can do comparing using method references found inside of your date object.
Ex.
In this instance unsortedDevices is a standard ObservableList to be used in a TablView.
SortedList<HistoryDisplayItem> sortedItems = new SortedList<>(unsortedDevices,
comparingInt(HistoryDisplayItem::getNumber));
hi i am sorting the date from the webservices ie json and i need to sort that based on the created date.normal sort Collections.sort is not working i need to format the date before sort how to do that
CommunicationEngine.post(getApplicationContext(), "sports",
mylibraryRequest, new AsyncHttpResponseHandler() {
com.loopj.android.http.AsyncHttpResponseHandler#onStart()
com.loopj.android.http.AsyncHttpResponseHandler#onSuccess(java.lang.String)
#Override
ObjectMapper sportsMapper = new ObjectMapper();## Heading ##try {
SportsResponse sportsResponse = sportsMapper.readValue(sportsResponseASString,SportsResponse.class);
if (null != sportsResponse) {
List<Assets> assets = sportsResponse.getAssets();
(Assets asset : assets) {
//sort list
sort_sportList.add(asset.getTitle()
.trim());
if(asset.getSportType() != null){
sort_sport.add(asset.getSportType().trim()); } EGLibContent eglibitem = new EGLibContent(
.getAssetEventDate(),
adapter.getKey("Contents");
adapter.addeglibcontent(eglibitem,ListView);
i use title normally by sorting collections.sort()
i want to sort getAssetEventDate(). the value returned from tthis function
So you want to sort the List using getAssetEventDate()?
getAssetEventDate returns a number?
Collection.sort(assets, new Comparator<Asset>() {
#Override
public int compare(Asset lhs, Asset rhs) {
if (lhs.getAssetEventDate() < rhs.getAssetEventDate() {
return -1;
} else if (lhs.getAssetEventDate() > rhs.getAssetEventDate() {
return 1;
} else {
return 0;
}
}
}
I've got this user class (this is a reduced version for the example, the real one has more parameters but they are implemented the same way):
public class User {
private int _userID;
private String _fullName;
public User(){
}
public User(int userID, String fullName){
this._userID = userID;
this._fullName = fullName;
}
int getUserID(){
return this._userID;
}
String getFullName(){
return this._fullName;
}
void setUserID(int userID){
this._userID = userID;
}
void setFullName(String fullName){
this._fullName = fullName;
}
}
And I want to retrieve a list from my MS SQL Server of this type of objects in Android, I'm using this method inside the connector helper class (the class in charge to make connection to the server using JDBC):
public List<User> getUsers(int ID){
java.sql.ResultSet result = null;
List<User> users = new ArrayList<User>();
User user = new User();
try {
connection = this.getConnection();
if (connection != null) {
//QUERY
String statement = "SELECT * Users WHERE groupID = "
+ ID;
Statement select = connection.createStatement();
//Calls Query
result = select.executeQuery(statement);
while (result.next()){
user.setUserID(result.getInt("UserID"));
user.setFullName(result.getString("FullName"));
System.out.println(result.getString("FullName"));
//Adds to the list
users.add(user);
}
result.close();
result = null;
closeConnection();
}
else {
System.out.println("Error: No active Connection");
}
} catch (Exception e) {
e.printStackTrace();
}
return users;
}
The data is retrieved well from the server according to the System.out.println I'm using in every iteration of the while, the problem is that the list is always filled with repeated information about the last user I retrieve, to clarify:
If I got users A, B and C, when I read user A, list has this structure:[A], when I read user B, list is:[B,B], when I read user C: [C,C,C], etc. So basically all the objects in the list are being overwritten by the last one read.
I've been struggling with this for hours, hope someone can spot the problem because I can't, thanks in advance for the help.
You instantiate a single User object before your loop, and then modify the same User object at each iteration. So you end up with N times the same User object added to your list. You must recreate a new User at each iteration:
while (result.next()){
User user = new User();
user.setUserID(result.getInt("UserID"));
...