1

我是新来的Android,并试图开发一个具有地图功能以及地方自动完成的应用程序。我使用谷歌地点Api来使我自己的自定义自动完成与Recycler视图。即使在清除搜索编辑文本后,一切工作都正常,除了Recycler视图显示预测。只有当我快速删除文本时才会发生。如果文本缓慢更改,则recyler视图将被清除,否则不会。我已尝试过,但无法找到解决方案。发布适配器和活动代码。任何帮助将不胜感激Android- Google将api autocomplete与回收站视图相关联?

public class AutoCompleteAdapter extends RecyclerView.Adapter<AutoCompleteAdapter.PredictionHolder> implements Filterable{ 
    private static final String TAG = AutoCompleteAdapter.class.getSimpleName(); 

    public interface PlaceAutoCompleteInterface{ 
     void onPlaceClick(ArrayList<PlaceAutoComplete> mResultList,int position); 
    } 

    private ArrayList<PlaceAutoComplete> mResultList; 
    private Context mContext; 
    private int mLayout; 
    private GoogleApiClient mGoogleApiClient; 
    private AutocompleteFilter mPlaceFilter; 
    private LatLngBounds mBounds; 

    private PlaceAutoCompleteInterface mPlaceClickInterface; 

    public AutoCompleteAdapter(Context mContext,int mLayout,GoogleApiClient mGoogleApiClient,LatLngBounds mBounds,AutocompleteFilter mPlaceFilter,PlaceAutoCompleteInterface mPlaceClickInterface){ 
     this.mContext=mContext; 
     this.mLayout=mLayout; 
     this.mGoogleApiClient=mGoogleApiClient; 
     this.mPlaceFilter=mPlaceFilter; 
     this.mBounds=mBounds; 
     this.mPlaceClickInterface=mPlaceClickInterface; 
    } 

    /** 
    * Setting Bounds for subsequent queries 
    */ 
    public void setmBounds(LatLngBounds mBounds){ 
     this.mBounds=mBounds; 
    } 

    /* 
    Clear List items 
    */ 
    public void clearList(){ 
     if(mResultList!=null && mResultList.size()>0){ 
      mResultList.clear(); 
     } 
    } 

    public static class PredictionHolder extends RecyclerView.ViewHolder{ 
     private TextView mAddress1,mAddress2; 
     private LinearLayout mPredictionLayout; 
     public PredictionHolder(View holder){ 
      super(holder); 
      mAddress1=(TextView)holder.findViewById(R.id.primary_address); 
      mAddress2=(TextView)holder.findViewById(R.id.secondary_address); 
      mPredictionLayout=(LinearLayout)holder.findViewById(R.id.prediction_layout); 
     } 
    } 

    /** 
    * Holder class for query result 
    */ 
    public class PlaceAutoComplete{ 
     private CharSequence placeId; 
     private CharSequence placeAddress1,placeAddress2; 

     public PlaceAutoComplete(CharSequence placeId,CharSequence placeAddress1,CharSequence placeAddress2){ 
      this.placeId=placeId; 
      this.placeAddress1=placeAddress1; 
      this.placeAddress2=placeAddress2; 
     } 

     public String getPlaceAddress1(){ 
      return placeAddress1.toString(); 
     } 
     public String getPlaceAddress2(){ 
      return placeAddress2.toString(); 
     } 

     public String getPlaceId(){ 
      return placeId.toString(); 
     } 

    } 


    @Override 
    public Filter getFilter() { 
     Filter filter=new Filter() { 
      @Override 
      protected FilterResults performFiltering(CharSequence constraint) { 

       FilterResults results=new FilterResults(); 
       ArrayList<PlaceAutoComplete> queryResults; 
       if(constraint!=null && constraint.length()>0) { 
        queryResults = getAutoComplete(constraint); 
        if(queryResults!=null){ 
         results.values = queryResults; 
         results.count = queryResults.size(); 
        } 
       } 
       // The API successfully returned results. 
       return results; 
      } 

      @Override 
      protected void publishResults(CharSequence constraint, FilterResults results) { 
       if(results!=null&& results.count > 0){ 
        // The API returned at least one result, update the data. 
        mResultList = (ArrayList<PlaceAutoComplete>) results.values; 
        notifyDataSetChanged(); 
       }else{ 
        // The API did not return any results, invalidate the data set. 
        clearList(); 
        notifyDataSetChanged(); 
       } 
      } 
     }; 
     return filter; 
    } 

    /** 
    * Method to call API for each user input 
    * @param constraint User input character string 
    * @return ArrayList containing suggestion results 
    */ 
    private ArrayList<PlaceAutoComplete> getAutoComplete(CharSequence constraint){ 
     if(mGoogleApiClient.isConnected()){ 
      //Making a query and fetching result in a pendingResult 

      PendingResult<AutocompletePredictionBuffer> results= Places.GeoDataApi 
        .getAutocompletePredictions(mGoogleApiClient,constraint.toString(),mBounds,mPlaceFilter); 

      //Block and wait for 60s for a result 
      AutocompletePredictionBuffer autocompletePredictions=results.await(60, TimeUnit.SECONDS); 

      final Status status=autocompletePredictions.getStatus(); 

      // Confirm that the query completed successfully, otherwise return null 
      if(!status.isSuccess()){ 
       Log.e(TAG, "Error getting autocomplete prediction API call: " + status.toString()); 
       autocompletePredictions.release(); 
       return null; 
      } 

      Log.i(TAG, "Query completed. Received " + autocompletePredictions.getCount() 
        + " predictions."); 

      // Copy the results into our own data structure, because we can't hold onto the buffer. 
      // AutocompletePrediction objects encapsulate the API response (place ID and description). 

      Iterator<AutocompletePrediction> iterator=autocompletePredictions.iterator(); 
      ArrayList resultList=new ArrayList<>(autocompletePredictions.getCount()); 
      while(iterator.hasNext()){ 
       AutocompletePrediction prediction=iterator.next(); 
       resultList.add(new PlaceAutoComplete(prediction.getPlaceId(),prediction.getPrimaryText(null),prediction.getSecondaryText(null))); 
      } 
      autocompletePredictions.release(); 
      return resultList; 
     }else{ 
      Log.e(TAG,"GoogleApiClient Not Connected"); 
      return null; 
     } 
    } 


    @Override 
    public PredictionHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     LayoutInflater mLayoutInflater=(LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     View convertView=mLayoutInflater.inflate(mLayout,parent,false); 
     PredictionHolder predictionHolder=new PredictionHolder(convertView); 
     return predictionHolder; 
    } 

    @Override 
    public void onBindViewHolder(PredictionHolder holder, final int position) { 
     holder.mAddress1.setText(mResultList.get(position).getPlaceAddress1()); 
     holder.mAddress2.setText(mResultList.get(position).getPlaceAddress2()); 
     holder.mPredictionLayout.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       mPlaceClickInterface.onPlaceClick(mResultList,position); 
      } 
     }); 
    } 

    @Override 
    public int getItemCount() { 
     if(mResultList!=null){ 
      return mResultList.size(); 
     }else{ 
      return 0; 
     } 
    } 

    public PlaceAutoComplete getItem(int position) { 
      return mResultList.get(position); 
    } 

} 

活动代码

public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener, AutoCompleteAdapter.PlaceAutoCompleteInterface { 

    private static final String TAG = MapsActivity.class.getSimpleName(); 
    private static final int MY_PERMISSIONS_ACCESS_FINE_LOCATION = 1; 
    private static final int REQUEST_CHECK_SETTINGS = 2; 

    private static final LatLngBounds BOUNDS_INDIA = new LatLngBounds(
      new LatLng(23.63936, 68.14712), new LatLng(28.20453, 97.34466)); 


    private GoogleMap mMap; 
    private Button mSelectButton; 
    private TextView mPrimaryAddress, mSecondaryAddress; 
    private LinearLayout mAddressLayout; 
    private ImageButton mCurrentLocation; 
    private Location mLocation; 
    private LocationRequest mLocationRequest; 

    protected GoogleApiClient mGoogleApiClient; 

    private Double mLatitude, mLongitude; 

    private EditText mSearchText; 
    private RecyclerView mRecyclerView; 
    private AutoCompleteAdapter mAdapter; 
    private ImageView mCustomMarker; 

    private static boolean sCameraMoved = true; 

    private AddressResultReceiver mAddressResultReceiver; 


    @Override 
    protected void onStop() { 
     mGoogleApiClient.disconnect(); 
     super.onStop(); 
    } 

    @Override 
    protected void onStart() { 
     super.onStart(); 
     mGoogleApiClient.connect(); 
    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_maps); 
     if (isGooglePlayServicesAvailable()) { 
      buildGoogleAPiClient(); 
     } else { 
      Log.e(TAG, "Google Play Services not available"); 
     } 
     createLocationRequest(); 
     getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 
     mSelectButton = (Button) findViewById(R.id.select_button); 
     mPrimaryAddress = (TextView) findViewById(R.id.firstAddress); 
     mSecondaryAddress = (TextView) findViewById(R.id.secondAddress); 
     mAddressLayout = (LinearLayout) findViewById(R.id.address_layout); 

     mCurrentLocation = (ImageButton) findViewById(R.id.get_current_location); 
     mCustomMarker = (ImageView) findViewById(R.id.map_custom_marker); 

     mSearchText = (EditText) findViewById(R.id.search_box); 
     mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); 

     MapFragment mapFragment = ((MapFragment)getFragmentManager().findFragmentById(R.id.map)); 
     mapFragment.getMapAsync(this); 

     isGpsOn(); 

     RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this); 
     mRecyclerView.setLayoutManager(layoutManager); 
     mAdapter = new AutoCompleteAdapter(this, R.layout.layout_recommendation, mGoogleApiClient, BOUNDS_INDIA, null, this); 
     mRecyclerView.setAdapter(mAdapter); 


     mAddressResultReceiver = new AddressResultReceiver(null); 

     mSearchText.setOnTouchListener(new View.OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       mSearchText.setCursorVisible(true); 
       return false; 
      } 
     }); 

     mSearchText.addTextChangedListener(new TextWatcher() { 
      @Override 
      public void beforeTextChanged(CharSequence s, int start, int count, int after) { 

      } 

      @Override 
      public void onTextChanged(CharSequence s, int start, int before, int count) { 

       if (!s.equals("") && mGoogleApiClient.isConnected()) { 
        mAdapter.getFilter().filter(s.toString()); 
       } else if (!mGoogleApiClient.isConnected()) { 
        Log.e(TAG, "API NOT CONNECTED"); 
       } 
      } 

      @Override 
      public void afterTextChanged(Editable s) { 
       if(s.toString().equals("")){ 
        mAdapter.getFilter().filter(null); 
       } 
      } 
     }); 

     mCurrentLocation.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       isGpsOn(); 
      } 
     }); 

     mSelectButton.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       if (mLongitude != null && mLongitude != null) { 
        Intent resultIntent = new Intent(); 
        resultIntent.putExtra("address1", mPrimaryAddress.getText().toString()); 
        resultIntent.putExtra("address2", mSecondaryAddress.getText().toString()); 
        resultIntent.putExtra("latitude", mLatitude); 
        resultIntent.putExtra("longitude", mLongitude); 
        setResult(Activity.RESULT_OK, resultIntent); 
        MapsActivity.this.finish(); 
       } else { 
        Toast.makeText(getBaseContext(), "Select a location", Toast.LENGTH_SHORT).show(); 
       } 
      } 
     }); 
    } 

    /** 
    * Method to initialize LocationRequest 
    */ 
    protected void createLocationRequest() { 
     mLocationRequest = new LocationRequest(); 
     mLocationRequest.setInterval(10000); 
     mLocationRequest.setFastestInterval(5000); 
     mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY | LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); 
    } 

    // Function to build the Google Api Client.. 
    protected synchronized void buildGoogleAPiClient() { 
     mGoogleApiClient = new GoogleApiClient.Builder(this) 
       .addOnConnectionFailedListener(this) 
       .addConnectionCallbacks(this) 
       .addApi(LocationServices.API) 
       .addApi(Places.GEO_DATA_API) 
       .build(); 
    } 

    @Override 
    public void onMapReady(GoogleMap googleMap) { 
     mMap = googleMap; 
     mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(20.5937, 78.9629), 4.0f)); 
    } 


    @Override 
    public void onPlaceClick(ArrayList<AutoCompleteAdapter.PlaceAutoComplete> mResultList, int position) { 
     if (mResultList != null) { 
      try { 
       String placeId = String.valueOf(mResultList.get(position).getPlaceId()); 

       mSearchText.setText(""); 
       InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 
       imm.hideSoftInputFromWindow(mSearchText.getWindowToken(), 0); 
       mSearchText.setCursorVisible(false); 
       PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi.getPlaceById(mGoogleApiClient, placeId); 
       placeResult.setResultCallback(new ResultCallback<PlaceBuffer>() { 
        @Override 
        public void onResult(@NonNull PlaceBuffer places) { 
         if (!places.getStatus().isSuccess()) { 
          // Request did not complete successfully 
          Log.e(TAG, "Place query did not complete. Error: " + places.getStatus().toString()); 
          places.release(); 
          return; 
         } 
         Place place = places.get(0); 
         mLatitude = place.getLatLng().latitude; 
         mLongitude = place.getLatLng().longitude; 
         mPrimaryAddress.setText(place.getName()); 
         mSecondaryAddress.setText(place.getAddress()); 
         mAddressLayout.setVisibility(View.VISIBLE); 
         sCameraMoved = false; 
         loadMap(); 
         places.release(); 
        } 
       }); 
      } catch (Exception e) { 
       e.printStackTrace(); 
       Log.e(TAG, e.toString()); 
      } 
     } 
    } 


    /** 
    * Method to display the location on Map 
    */ 
    public void loadMap() { 
     if (mLatitude != null && mLongitude != null) { 
      CameraPosition cameraPosition = new CameraPosition.Builder() 
        .target(new LatLng(mLatitude, mLongitude))  // Sets the center of the map to location user 
        .zoom(18)     // Sets the zoom// Sets the tilt of the camera to 30 degrees 
        .build();     // Creates a CameraPosition from the builder 
      mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)); 
      mCustomMarker.setVisibility(View.VISIBLE); 

      mMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() { 
       @Override 
       public void onCameraIdle() { 
        Location location = new Location(""); 
        if (sCameraMoved) { 
         mLatitude = mMap.getCameraPosition().target.latitude; 
         mLongitude = mMap.getCameraPosition().target.longitude; 
         location.setLatitude(mLatitude); 
         location.setLongitude(mLongitude); 
         convertLocationToAddress(location); 
        } 
        sCameraMoved = true; 
       } 
      }); 
     } 
    } 

    @Override 
    public void onConnected(@Nullable Bundle bundle) { 
     startLocationUpdates(); 
    } 

    @Override 
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 
     switch (requestCode) { 
      case MY_PERMISSIONS_ACCESS_FINE_LOCATION: { 
       if (grantResults.length > 0 
         && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
        mCurrentLocation.setVisibility(View.VISIBLE); 
       } else { 
        mCurrentLocation.setVisibility(View.GONE); 
       } 
       return; 
      } 
     } 
    } 

    protected void startLocationUpdates() { 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
      if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { 
       mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); 
      } else { 
       ActivityCompat.requestPermissions(this, 
         new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 
         MY_PERMISSIONS_ACCESS_FINE_LOCATION); 
       Log.d(TAG, "Permission Not Granted"); 
      } 

     } else { 
      LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); 
      mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); 
     } 
    } 

    /** 
    * Method to stop the regular location updates 
    */ 
    protected void stopLocationUpdates() { 
     if (mGoogleApiClient.isConnected()) { 
      LocationServices.FusedLocationApi.removeLocationUpdates(
        mGoogleApiClient, this); 
     } 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     if (mGoogleApiClient.isConnected()) { 
      startLocationUpdates(); 
     } 
    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 
     stopLocationUpdates(); 
    } 

    @Override 
    public void onConnectionSuspended(int i) { 
     Log.e(TAG, "Connection Suspended"); 
    } 

    @Override 
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { 
     Log.e(TAG, "Connection Failed"); 
    } 

    @Override 
    public void onLocationChanged(Location location) { 
     mLocation = location; 
    } 


    /** 
    * Method to get current location and do reverse geocoding of the location 
    */ 
    private void getCurrentLocationAddress() { 
     if (mLocation != null) { 
      mLatitude = mLocation.getLatitude(); 
      mLongitude = mLocation.getLongitude(); 
      convertLocationToAddress(mLocation); 
      loadMap(); 
     } 
    } 

    /** 
    * Method to check if google play services are enabled or not 
    * 
    * @return boolean status 
    */ 
    public boolean isGooglePlayServicesAvailable() { 
     GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance(); 
     int status = googleApiAvailability.isGooglePlayServicesAvailable(this); 
     if (status != ConnectionResult.SUCCESS) { 
      if (googleApiAvailability.isUserResolvableError(status)) { 
       googleApiAvailability.getErrorDialog(this, status, 2404).show(); 
      } 
      return false; 
     } 
     return true; 
    } 

    /** 
    * Method to check if GPS is on or not 
    */ 
    private void isGpsOn() { 
     LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder() 
       .addLocationRequest(mLocationRequest); 

     PendingResult<LocationSettingsResult> result = 
       LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build()); 
     result.setResultCallback(new ResultCallback<LocationSettingsResult>() { 
      @Override 
      public void onResult(@NonNull LocationSettingsResult locationSettingsResult) { 
       final Status status = locationSettingsResult.getStatus(); 
       switch (status.getStatusCode()) { 
        case LocationSettingsStatusCodes.SUCCESS: 
         getCurrentLocationAddress(); 
         break; 
        case LocationSettingsStatusCodes.RESOLUTION_REQUIRED: 
         try { 
          status.startResolutionForResult(
            MapsActivity.this, 
            REQUEST_CHECK_SETTINGS); 
         } catch (IntentSender.SendIntentException e) { 
          Log.e(TAG, "Exception : " + e); 
         } 
         break; 
        case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE: 
         Log.e(TAG, "Location settings are not satisfied."); 
         break; 
       } 
      } 
     }); 

    } 

    /** 
    * Method to convert latitude and longitude to address via reverse-geocoding 
    */ 
    private void convertLocationToAddress(Location location) { 
     Intent intent = new Intent(this, GeoCoderIntentService.class); 
     intent.putExtra(Constants.RECEIVER, mAddressResultReceiver); 
     intent.putExtra(Constants.LOCATION_DATA_EXTRA, location); 
     startService(intent); 
    } 


    private class AddressResultReceiver extends ResultReceiver { 

     public AddressResultReceiver(Handler handler) { 
      super(handler); 
     } 

     protected void onReceiveResult(final int resultCode, Bundle resultData) { 

      final String address1 = resultData.getString(Constants.ADDRESS_DATA_KEY1); 
      final String address2 = resultData.getString(Constants.ADDRESS_DATA_KEY2); 
      runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        if (resultCode == Constants.SUCCESS_RESULT) { 
         mPrimaryAddress.setText(address1); 
         mSecondaryAddress.setText(address2); 
         mAddressLayout.setVisibility(View.VISIBLE); 
        } else { 
         Log.e(TAG, "Error while fetching data"); 
         mLatitude = mLongitude = null; 
         mPrimaryAddress.setText(address1); 
         mSecondaryAddress.setText(""); 
        } 
       } 
      }); 
     } 
    } 

} 

回答

0

试图改变如下面的代码,

@Override 
     public void onTextChanged(CharSequence s, int start, int before, int count) { 

      if (!s.equals("")) { 
       if(mGoogleApiClient.isConnected()){ 
       mAdapter.getFilter().filter(s.toString()); 
       }else{ 
       Log.e(TAG, "API NOT CONNECTED");     
        } 

      } else { 
       mAdapter.mResultList.clear();//make mResultList as public 
       mAdapter.notifyDataSetChanged(); 

      } 
     }