9

I'm fetching 3 String values from the database and then I'm converting it to Long and then I'm calculating a difference and then putting this calculated Long value in a method as parameter. I'm using FastAdapter.

The filterRequests(List <Long> l) is a method in MainActivity which do the logic of filtering requests/content based on the long l.

entire adapter:

public class GRModelClass extends AbstractItem<GRModelClass, GRClass.ViewHolder>{

    private static final ViewHolderFactory<? extends ViewHolder> FACTORY = new ItemFactory();

    String postedBy, postedTime, currentLat, currentLng, utcFormatDateTime, userEmail, userID;
    String startDateTimeInEpoch, endDateTimeInEpoch;
    DatabaseReference primaryDBKey;
    long ms;
    String itemID;

    public GRModelClass(){}

    public GRModelClass(String postedBy, String postedTime, String currentLat, String currentLng, String utcFormatDateTime, String userEmail, String userID, String startDateTimeInEpoch, String endDateTimeInEpoch, DatabaseReference primaryDBKey) {
        this.postedBy = " " + postedBy;
        this.postedTime = postedTime;
        this.currentLat = currentLat;
        this.currentLng = currentLng;
        this.utcFormatDateTime = utcFormatDateTime;
        this.userEmail = userEmail;
        this.userID = userID;
        this.startDateTimeInEpoch = startDateTimeInEpoch;
        this.endDateTimeInEpoch = endDateTimeInEpoch;
        this.primaryDBKey = primaryDBKey;
    }

    @Exclude
    public Map<String, Object> toMap() {
        HashMap<String, Object> result = new HashMap<>();
        result.put("pBy", postedBy);
        result.put("cLat", currentLat);
        result.put("cLng", currentLng);
        result.put("utcFormatDateTime", utcFormatDateTime);
        result.put("userEmail", userEmail);
        result.put("userID", userID);
        result.put("startDateTime", startDateTimeInEpoch);
        result.put("endDateTime", endDateTimeInEpoch);

        return result;
    }


    @Override
    public int getType() {
        return R.id.recycler_view;
    }

    @Override
    public int getLayoutRes() {
        return R.layout.sr_layout;
    }

    @Override
    public void bindView(final ViewHolder holder, List list) {
        super.bindView(holder, list);

        holder.postedBy.setText(postedBy);
        holder.postedBy.setTypeface(null, Typeface.BOLD);
        holder.startDateTimeInEpoch.setText(startDateTimeInEpoch);
        holder.startDateTimeInEpoch.setVisibility(View.INVISIBLE);
        holder.endDateTimeInEpoch.setText(endDateTimeInEpoch);
        holder.endDateTimeInEpoch.setVisibility(View.INVISIBLE);

        MainActivity.filterButton.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem menuItem) {
                holder.geoQuery = holder.geoFireReference.queryAtLocation(new GeoLocation(holder.currentLatDouble, holder.currentLngDouble), 5);

            holder.geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
                @Override
                public void onKeyEntered(String key, GeoLocation location) {
                    primaryDBKey.child(key).child("startDateTimeInEpoch").addListenerForSingleValueEvent(new ValueEventListener() {
                        @Override
                        public void onDataChange(DataSnapshot dataSnapshot) {
                            if (dataSnapshot.getValue() != null) {
                                holder.startTimeDateInEpochLong2 = Long.parseLong(dataSnapshot.getValue().toString());
                                holder.now = System.currentTimeMillis() / 1000;
                                holder.diffNowsdtel.add(holder.startTimeDateInEpochLong2 - holder.now);
                                Log.d("log1", String.valueOf(holder.diffNowsdtel));

                                Handler handler = new Handler();
                                handler.postDelayed(new Runnable() {
                                    @Override
                                    public void run() {
                                        if(holder.mContext instanceof MainActivity){
                                            ((MainActivity)holder.mContext).filterRequests(holder.diffNowsdtel);
                                            Log.d("log2", String.valueOf(holder.diffNowsdtel));
                                        }
                                    }
                                }, 1500);
                            }
                        }

                        @Override
                        public void onCancelled(DatabaseError databaseError) {

                        }
                    });
                }

                @Override
                public void onKeyExited(String key) {

                }

                @Override
                public void onKeyMoved(String key, GeoLocation location) {

                }

                @Override
                public void onGeoQueryReady() {

                }

                @Override
                public void onGeoQueryError(DatabaseError error) {

                }
            });
                return true;
            }
        });

    }

    /**
     * our ItemFactory implementation which creates the ViewHolder for our adapter.
     * It is highly recommended to implement a ViewHolderFactory as it is 0-1ms faster for ViewHolder creation,
     * and it is also many many timesa more efficient if you define custom listeners on views within your item.
     */
    protected static class ItemFactory implements ViewHolderFactory<ViewHolder> {
        public ViewHolder create(View v) {
            return new ViewHolder(v);
        }
    }

    /**
     * return our ViewHolderFactory implementation here
     *
     * @return
     */
    @Override
    public ViewHolderFactory<? extends ViewHolder> getFactory() {
        return FACTORY;
    }


    // Manually create the ViewHolder class
    protected static class ViewHolder extends RecyclerView.ViewHolder {

        TextView postedBy, userID, currentLt, currentLn, requestID, postedFrom;
        TextView startDateTimeInEpoch, endDateTimeInEpoch, diffNowsdtelTV;
        LinearLayout linearLayout;
        long difference, differenceCurrentStartTime, handlerGap;
        long startTimeDateInEpochLong2;
        public static long now;
        List<Long> diffNowsdtel;
        Context mContext;
        DatabaseReference firebaseDatabase;
        GeoFire geoFireReference;
        GeoQuery geoQuery;


        public ViewHolder(final View itemView) {
            super(itemView);

            postedBy = (TextView) itemView.findViewById(R.id.postedBy);
            startDateTimeInEpoch = (TextView) itemView.findViewById(R.id.startTimeDateInEpoch);
            endDateTimeInEpoch = (TextView) itemView.findViewById(R.id.endTimeDateInEpoch);
            diffNowsdtelTV = (TextView) itemView.findViewById(R.id.diffNowsdtelTV);

            this.mContext = itemView.getContext();

        private boolean isNetworkAvailable() {
            ConnectivityManager connectivityManager
                    = (ConnectivityManager) itemView.getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
            return activeNetworkInfo != null && activeNetworkInfo.isConnected();
        }
    }
}

The problem is that when I'm logging log1, I'm getting all the 3 values shown in Logcat, but when I'm logging log2 only the last calculated value is getting shown and that is the value using which filterRequests(Long l) is getting called.

Update - after updating the adapter code, log1 and log2 now shows this:

 D/log1: [2197]
 D/log1: [2197, -1007]
 D/log1: [2197, -1007, 4003]

 D/log2: [2197, -1007, 4003]

filterRequests() method is the method in which the logic to filter content based on time is done. The parameter which goes in filterRequests() is holder.diffNowsdtel which has 3 long values for now and do it should do the logic based on it.. if the long value is <=900 the content which has the long value -1007 should be shown and when long value is >900, the content which has the long value 2197 and 4003 should be shown.

here's the code:

public void filterRequests(final List<Long> l) {

    final int size = l.size();

            Log.d("lng", String.valueOf(l));

                    if (isNetworkAvailable()) {
                        if (chkBoxLiveRqsts.isChecked()) {



                                    firebaseDatabase.child(key).addValueEventListener(new ValueEventListener() {
                                        @Override
                                        public void onDataChange(DataSnapshot dataSnapshot) {
                                            if (dataSnapshot.getValue() != null) {
                                                for (int i = 0; i < size; i++){
                                                    if (l.get(i) <= 900) {
                                                    ...       
                                                    } else {
                                                    }
                                                }
                                                progressDialogAdding.dismiss();
                                            } else {
                                            }
                                        }

                                        @Override
                                        public void onCancelled(DatabaseError databaseError) {
                                        }
                                    });
                                }

                                ...
                            });
                        } else if (chkBoxSFLRqsts.isChecked()) {
                            fastItemAdapter.clear();
                            firebaseDatabase.child(key).addValueEventListener(new ValueEventListener() {
                                        @Override
                                        public void onDataChange(DataSnapshot dataSnapshot) {
                                            if (dataSnapshot.getValue() != null) {
                                                for (int i = 0; i < size; i++) {
                                                    if (l.get(i) > 900) {
                                                        ...

                                                    } else {
                                                    }
                                                }
                                                progressDialogAdding.dismiss();
                                            } else {
                                            }
                                        }

                                        @Override
                                        public void onCancelled(DatabaseError databaseError) {
                                        }
                                    });
                                }
                                ...
                        } 
                    } else {
                        Snackbar snackbar = Snackbar
                                .make(coordinatorLayout, "No internet connection", Snackbar.LENGTH_SHORT);
                        snackbar.show();
                        progressDialogAdding.dismiss();
                    }
                }
            });
            dialog = builder.create();
        dialog.show();
}

Log value of lng:

D/lng: [2197, -1007, 4003]

What I want is that the filterRequests(Long l) method should use all the values of holder.diffNowsdtelTV.getText().toString() and do the logic using them.

I'm sorry for ambiguous question. Please help me with this issue!

Hammad Nasir
  • 2,889
  • 7
  • 52
  • 133
  • 1
    What about some [mcve] here ? It seems to be a simple problem ... – AxelH Dec 07 '16 at 15:30
  • @AxelH what do you mean by that, bro? – Hammad Nasir Dec 07 '16 at 15:36
  • The amount of code you have included is a lot. Also, as AxelH said, it sounds like a simple problem. If you could remove all the unnecessary code and include the ones that are needed then it would be helpful for other people to answer your question. Moreover, it's not really clear what you are trying to do in `filterRequests(..)`. Read the link he provided – denvercoder9 Dec 07 '16 at 15:39
  • @RafiduzzamanSonnet I have edited it to my best... please take a look – Hammad Nasir Dec 07 '16 at 15:53
  • First, you are speaking about `MainActivitiy.filterRequest(Long l)` but all I can find is `MainActivitiy.filterRequest(final List l)` then, what I understand if I translate the methods you want is [What are captured variables in Java Local Classes](http://stackoverflow.com/q/22025161/4391450). And that could be resume in an example of 5line. PS : Don't _bro_ me please ;) – AxelH Dec 07 '16 at 18:26
  • I should have add that I think having that many nested local class might be a bad design. You should think about create some Class to clean that code. – AxelH Dec 07 '16 at 18:34
  • Last think ... there is some strange thing in your code, could you explain how `holder.diffNowsdtel = holder.startTimeDateInEpochLong2 - holder.now;` can compile if `holder.diffNowdtel`is declared has `List` ... – AxelH Dec 07 '16 at 18:41
  • @AxelH Thanks for pointing out the silly mistakes in the question... I've edited it. Any help now? – Hammad Nasir Dec 07 '16 at 19:09
  • About what, you have your answer or not? This question is closed... – AxelH Dec 07 '16 at 19:23
  • @AxelH this question: http://stackoverflow.com/q/41023421/6144372 – Hammad Nasir Dec 07 '16 at 19:26

3 Answers3

2

What you are doing

In your ViewHolder diffNowsdtel is declared as long (which saves latest value) whenever you are logging log1 Logger displays (latest value from diffNowsdtel so your log displays different values because bindView calls many times whenever you are updating your row or complete dataset)

D/log1: -22136
D/log1: -22403
D/log1: -25094

Inside onMenuItemClick you are fetching value directly from your TextView which is now -25094 that's why you have only one value in your TextView and log says

D/log2: -25094

What you should do

Set Tag using holder.diffNowsdtelTV.setTag(your database key or row_id) and inside your onMenuItemClick get your tag using

Object someTagName = (Object) holder.diffNowsdtelTV.getTag();

Now fetch your 3 String values from the database using value stored in someTagName and then do your calculations.

Edit

Actually you need 3 values to do your calculation, while in your current logic you only have the latest value stored in diffNowsdtel. So now you need a logic to store trice your values somewhere and inside onMenuItemClick use them but if you will go to save trice your values you have to change your diffNowsdtel to long[] or List<Long> and save your every value in it on every bindView call which needs some logic so simplest way is to pass your unique database column say primary key and save it in your GRModelClass

String primaryDbKey;

public GRModelClass(String primaryDbKey, ...) {
    this.primaryDbKey = primaryDbKey;
    ....
}

Inside your onMenuItemClick use primaryDbKey to fetch your 3 String values from your database table(which you are doing somewhere else) and then do your calculations.


Edit

You made a list with Long, both List and Long are not primitive data types. In your question you are comparing primitive and non primitive data types, for comparison both sides of a comparator should be of same data types.

What you are doing:

if (l.get(i) <= 900)

Here l.get(i) returns a Long value where as 900 is integer value.

What you should do:

Simply compare your l.get(i) with Long by doing 900L

if (l.get(i) <= 900L)

Or

if (l.get(i) > 900L)
Haris Qurashi
  • 2,104
  • 1
  • 13
  • 28
  • hey... thanks for answering. I am still confused about **What you should do** part. Please write some code or explain more clearly. Please? Thanks again. – Hammad Nasir Dec 04 '16 at 18:37
  • based on your '**Edit**', I tried it and I have updated the adapter and the `logcat` in the question. `log2` also shows 3 values now just like `log1`, but all the 3 values are same. – Hammad Nasir Dec 05 '16 at 02:06
  • It is because you are still using `diffNowsdtel` in `onDataChange` which is **-29601**. You should calculate your result based on your 3 `String` values and use them. Do not save its value in variable if you do you will have the latest value in your variable or make an `long[]` or `List `and save your 3 values in it – Haris Qurashi Dec 05 '16 at 07:23
  • Salaam bro... you just edited a question of mine. That's what I tried after your previous comment here. :( – Hammad Nasir Dec 07 '16 at 13:24
  • com start our discuss in chat – Haris Qurashi Dec 07 '16 at 13:26
  • please have a look at edited question... I have updated it. – Hammad Nasir Dec 07 '16 at 15:28
  • Accept this answer as your actual problem has been solved, then ask a separate question with given details or move this conversation to chat room – Haris Qurashi Dec 07 '16 at 16:32
  • done... please help with the new quesion: http://stackoverflow.com/questions/41023421/how-to-compare-values-stored-in-listlong-with-a-long-value – Hammad Nasir Dec 07 '16 at 17:12
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/130033/discussion-between-haris-qureshi-and-hammad-nasir). – Haris Qurashi Dec 07 '16 at 17:39
1

Try to set initialize the value you want within the onBindView

   Log.d("diffNowsdtel", holder.diffNowsdtelTV.getText().toString());
    final String val = holder.diffNowsdtelTV.getText().toString();

            MainActivity.filterButton.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem menuItem) {
                    if(holder.mContext instanceof MainActivity){
                        ((MainActivity)holder.mContext).filterRequests(Long.parseLong(val));
                        Log.d("diffNowsdtel2",val);
                    }
                    return true;
                }
            });
Niza Siwale
  • 2,390
  • 1
  • 18
  • 20
1

You have a statically defined object called filterButton in MainActivity. Every time bindView is called for a new view, it is replacing the menu item listener for that button. So when you click that menu item, it is only calling the handler you set on for the last item that bindView was called for. That's why you only see one log entry when that filter button is pressed.

Doug Simonton
  • 1,021
  • 8
  • 14
  • Please tell me about how can I get the feature start working? – Hammad Nasir Dec 04 '16 at 03:23
  • You could try setting the item click listener one time when you create the filter button in the activity, rather than in bindView. The listener can get all the items in the list and loop through them, making the call to filterRequests for each item. That way, each time you click the button, the listener will call filterRequests for all your items, and you should get 3 log messages. – Doug Simonton Dec 04 '16 at 05:11
  • but then I have to set the `holder.diffNowsdtelTV.getText().toString()` statically to pass it into `filterRequests()` as a parameter and calling it from `MainActivity`. This will again show only take/show only the last calculated value of `holder.diffNowsdtelTV.getText().toString()`. :/ – Hammad Nasir Dec 04 '16 at 07:21