0

I have this fragment where I have and edit text , a button and a recycler view. When I click the button for the first time it has the expected behavior but if I change the edit text content and click the button again it doesn´t update my recycler view. What am I doing wrong? Since I am repeating the process of making an Api call every click

Fragment

public class SearchFragment extends Fragment implements View.OnClickListener {

    private RestaurantAdapter mAdapter;
    private RecyclerView mRecyclerView;
    protected static List<Restaurant_> restaurantsList;
    private Context context;
    private static OnRestaurantClickedListener listener;
    private FirebaseAuth mAuth;

    private EditText keyword;

    private FusedLocationProviderClient mFusedLocationClient;


    public SearchFragment() {
    }

    public static OnRestaurantClickedListener getListener() {
        return listener;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        context = getContext();
        mAuth = FirebaseAuth.getInstance();
        restaurantsList = new ArrayList<>();
        mAdapter = new RestaurantAdapter(context, restaurantsList, getActivity());
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View mContentView = inflater.inflate(R.layout.fragment_search, container, false);
        mRecyclerView = mContentView.findViewById(R.id.recycler_view);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(mContentView.getContext()));
        mRecyclerView.setAdapter(mAdapter);

        keyword = mContentView.findViewById(R.id.keyword);
        keyword.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {
                if ((keyEvent != null && keyEvent.getKeyCode() == KeyEvent.KEYCODE_ENTER) || (actionId == EditorInfo.IME_ACTION_SEARCH))
                    getRestaurants();
                return false;
            }
        });

        ImageButton searchButton = mContentView.findViewById(R.id.search);
        searchButton.setOnClickListener(this);

        return mContentView;
    }

    @Override
    public void onResume() {
        super.onResume();
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            listener = (OnRestaurantClickedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnButtonClicked");
        }
    }

    @SuppressLint("MissingPermission")
    private void getRestaurants() {
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(getActivity());
        mFusedLocationClient.getLastLocation().addOnSuccessListener(getActivity(), new OnSuccessListener<Location>() {
            @Override
            public void onSuccess(final Location location) {
                if (location != null) {
                    SharedPreferences mSettings = PreferenceManager.getDefaultSharedPreferences(context);
                    String sort = mSettings.getString("sort", "rating");
                    String order = mSettings.getString("order", "desc");
                    double radius = Double.parseDouble(mSettings.getString("radius", "10"));
                    radius = radius * 1000;
                    RetrofitZomato.getApi().searchByName(keyword.getText().toString(), location.getLatitude(), location.getLongitude(),
                            20, radius, sort, order, getActivity().getResources().getString(R.string.user_key))
                            .enqueue(new Callback<SearchResponse>() {
                                @Override
                                public void onResponse(Call<SearchResponse> call, Response<SearchResponse> response) {
                                    if (restaurantsList.size() != 0) {
                                        restaurantsList.clear();
                                        mAdapter.notifyDataSetChanged();
                                    }
                                    List<Restaurant> restaurants = response.body().getRestaurants();
                                    for (int i = 0; i < restaurants.size(); i++) {
                                        double distance = calculateDistance(Double.parseDouble(restaurants.get(i).getRestaurant().getLocation().getLatitude()),
                                                Double.parseDouble(restaurants.get(i).getRestaurant().getLocation().getLongitude()),
                                                location.getLatitude(), location.getLongitude());
                                        distance = (double) Math.round(distance * 100d) / 100d;
                                        restaurants.get(i).getRestaurant().setDistance(distance);
                                        restaurantsList.add(restaurants.get(i).getRestaurant());
                                        mAdapter.notifyItemInserted(i);
                                    }
                                }

                                @Override
                                public void onFailure(Call<SearchResponse> call, Throwable t) {
                                    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                                    builder.setMessage("Couldn't find any nearby restaurants");
                                    AlertDialog mDialog = builder.create();
                                    mDialog.show();
                                }
                            });
                }
            }
        }).addOnFailureListener(getActivity(), new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Toast.makeText(getActivity(), "It wasn't possible to determine your location", Toast.LENGTH_LONG).show();
            }
        });
    }

    private double calculateDistance(double latRestaurant, double lonRestaurant, double myLat, double myLon) {
        if ((myLat == latRestaurant) && (myLon == lonRestaurant)) {
            return 0;
        } else {
            double theta = myLon - lonRestaurant;
            double dist = Math.sin(Math.toRadians(myLat)) * Math.sin(Math.toRadians(latRestaurant))
                    + Math.cos(Math.toRadians(myLat)) * Math.cos(Math.toRadians(latRestaurant)) * Math.cos(Math.toRadians(theta));
            dist = Math.acos(dist);
            dist = Math.toDegrees(dist);
            dist = dist * 60 * 1.1515;
            dist = dist * 1.609344;
            return dist;
        }
    }

    @Override
    public void onClick(View view) {
        int id = view.getId();
        if (id == R.id.search) {
            getRestaurants();
        }
    }
//    @Override
//    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
//        super.onActivityCreated(savedInstanceState);
//        searchViewModel = ViewModelProviders.of(this).get(SearchViewModel.class);
//        // TODO: Use the ViewModel
//    }

}

1 Answers1

0

note that with every getRestaurants call you are calling getFusedLocationProviderClient and addOnSuccessListener, keeping old one registered and left... maybe these multiple instances of listeners are reason of this behavior?

move this line to onAttach

mFusedLocationClient = LocationServices.getFusedLocationProviderClient(getActivity());

for getting called once. then make your SearchFragment implementing OnSuccessListener and set for FusedLocationProviderClient. your click should fire request for new location, and your current code with getLastLocation may be also handled in onAttach

edit: real answer - comment copy

try to remove mAdapter.notifyItemInserted(i); line and move mAdapter.notifyDataSetChanged(); out of if condition on the end of method (after for loop). I don't see nothing suspicious in your code, looks fine...

snachmsm
  • 17,866
  • 3
  • 32
  • 74
  • i didn´t understand the last part –  Sep 07 '20 at 12:15
  • put some `Log` in `onSuccess` and in `onResponse` - check what it is printing with first and all further (not working) clicks – snachmsm Sep 07 '20 at 12:38
  • "and your current code with getLastLocation may be also handled in onAttach " this part –  Sep 07 '20 at 12:41
  • `getLastLocation` will return last location, as suspected. but you aren't calling nowhere `requestLocationUpdates`, so this last location is fixed and never changes if any other app in background isn't requesting for location also. I'm assuming that last location should be used on start `Fragment` (so in `onAttach`), but for real current location (not from 2h ago..) you should request new location with every button/`ENTER` click – snachmsm Sep 07 '20 at 12:43
  • check with logging when are `onSuccess` and `onResponse` methods gets called, how often. print attributes which are passed into them (`Location`, which will be same object with every call, and `Response` is this proper response, respecting passed query from `keyword` `TextView` – snachmsm Sep 07 '20 at 12:48
  • I do request a new location every click. My problem is that for example I search "Wok" , the list updates to Wok to Walk restaurants. If I search for McDonald's next and click the button it stays the Wok to Walk list. But if e click on an item and see the details and then press back to return to the list, the McDonald's list is in there –  Sep 07 '20 at 12:56
  • try to remove `mAdapter.notifyItemInserted(i);` line and move `mAdapter.notifyDataSetChanged();` out of `if` condition on the end of method (after `for` loop). I don't see nothing suspicious in your code, looks fine... – snachmsm Sep 07 '20 at 13:00
  • Done. If you don´t mind can you take a look at this question please? https://stackoverflow.com/questions/63779965/android-how-to-set-location-in-map –  Sep 07 '20 at 14:53
  • @snachmsm need help here --> https://stackoverflow.com/questions/64495233/retrofit-call-inside-an-adapter-in-android – android dev Oct 23 '20 at 10:04