2017-07-20 13 views
0

次はRecyclerView用のアダプタです。TextViewのうちの1つを更新する必要があります。Android:現在のメインスレッドでmFusedLocationClientコールバック(結果の場所)を使用する方法

、現在の位置を取得し、私は以下のコードでつもりですし、ちょうどランタイム許可すると、アプリでGPSを有効にしている場合、私はライン上のNPEに直面mFusedLocationClient.requestLocationUpdates(mFusedLocationRquest,mLocationCallback,null);

を使用していますする:

float distance = updatedLoc.distanceTo(des); 

gpsが既に有効になっている状態でiアプリを開いてもアプリケーションがクラッシュすることはありません(おそらく、最後の既知のlocがnullでないためです)。

updatedLocがヌルでないことを確認するには、ロケーションコールバック後にTextViewが更新されていることを確認してください。このAPIのコールバックで

createLocationCallback()、私は事前に(グローバルVARとしてホルダーを使用してみましたが、それは厄介だったとの項目が適切に更新されませんでした。)

おかげ正しくのTextViewを更新することができません。

public class PlaceListAdapter extends RecyclerView.Adapter<PlaceListAdapter.PlaceViewHolder> implements android.location.LocationListener{ 

    private static final long LOCATION_REFRESH_TIME = 2000; 
    private static final float LOCATION_REFRESH_DISTANCE = 100; 
    private static final int MY_PERMISSION_ACCESS_COURSE_LOCATION = 1001; 
    private Context mContext; 
    private PlaceBuffer mPlaces; 
    Location updatedLoc = null; 
    PlaceViewHolder myHolder; 
    boolean canGetLocation = false; 
    android.location.LocationListener locationListener; 
    double lat1,long1; 
    MySimpleCallback mySimpleCallback; 
    String dist; 
    private FusedLocationProviderClient mFusedLocationClient; 
    private LocationRequest mFusedLocationRquest; 
    private LocationCallback mLocationCallback; 

    /** 
    * Creates a callback for receiving location events. 
    */ 
    private void createLocationCallback() { 
     mLocationCallback = new LocationCallback() { 
      @Override 
      public void onLocationResult(LocationResult locationResult) { 
       super.onLocationResult(locationResult); 

       updatedLoc = locationResult.getLastLocation(); 

       Log.d("testingvalue",String.valueOf(updatedLoc==null)); 
       //mLastUpdateTime = DateFormat.getTimeInstance().format(new Date()); 

      } 
     }; 
    } 


    /** 
    * Constructor using the context and the db cursor 
    * 
    * @param context the calling context/activity 
    */ 
    public PlaceListAdapter(Context context, PlaceBuffer places) { 
     this.mContext = context; 
     this.mPlaces = places; 
     mFusedLocationClient = LocationServices.getFusedLocationProviderClient(mContext); 

     createLocationCallback(); 
     createLocationRequest(); 

     if (ActivityCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) 
       != PackageManager.PERMISSION_GRANTED) { 
      ActivityCompat.requestPermissions((Activity) mContext, 
        new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, 
        101); 
     } 

     mFusedLocationClient.requestLocationUpdates(mFusedLocationRquest,mLocationCallback,null); 

    } 

    private void createLocationRequest() { 
     mFusedLocationRquest = new LocationRequest(); 

     // Sets the desired interval for active location updates. This interval is 
     // inexact. You may not receive updates at all if no location sources are available, or 
     // you may receive them slower than requested. You may also receive updates faster than 
     // requested if other applications are requesting location at a faster interval. 
     mFusedLocationRquest.setInterval(100); 

     // Sets the fastest rate for active location updates. This interval is exact, and your 
     // application will never receive updates faster than this value. 
     mFusedLocationRquest.setFastestInterval(100); 

     mFusedLocationRquest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); 

    } 

    /** 
    * Called when RecyclerView needs a new ViewHolder of the given type to represent an item 
    * 
    * @param parent The ViewGroup into which the new View will be added 
    * @param viewType The view type of the new View 
    * @return A new PlaceViewHolder that holds a View with the item_place_card layout 
    */ 
    @Override 
    public PlaceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     // Get the RecyclerView item layout 
     LayoutInflater inflater = LayoutInflater.from(mContext); 
     View view = inflater.inflate(R.layout.item_place_card, parent, false); 
     return new PlaceViewHolder(view); 
    } 

    /** 
    * Binds the data from a particular position in the cursor to the corresponding view holder 
    * 
    * @param holder The PlaceViewHolder instance corresponding to the required position 
    * @param position The current position that needs to be loaded with data 
    */ 
    @Override 
    public void onBindViewHolder(PlaceViewHolder holder, int position) { 
     String placeName = mPlaces.get(position).getName().toString(); 
     String placeAddress = mPlaces.get(position).getAddress().toString(); 

     double lat = mPlaces.get(position).getLatLng().latitude; 
     double lng = mPlaces.get(position).getLatLng().longitude; 

     //Location currentLocation = getCurrentLocation(); 

     //Location currLoc = new GPSTracker(mContext).getLocation(); 

     //Toast.makeText(mContext, "distance is" + dist + "km", Toast.LENGTH_SHORT).show(); 

     Location des = new Location("destination"); 

     des.setLatitude(lat); 
     des.setLongitude(lng); 

     float distance = updatedLoc.distanceTo(des); 

     distance = distance/1000; 

     dist = ""; 
     if (distance < 1) { 
      dist = "less than km away"; 
     } else { 
      dist = String.format("%.2f", distance) + " km"; 
     } 


     holder.nameTextView.setText(placeName); 
     holder.addressTextView.setText(dist); 

     holder.taskTextView.setText(MainActivity.preference.getString(mPlaces.get(position).getId(), "chv")); 
    } 

    public void swapPlaces(PlaceBuffer newPlaces) { 
     mPlaces = newPlaces; 
     if (mPlaces != null) { 
      // Force the RecyclerView to refresh 
      this.notifyDataSetChanged(); 

     } 
    } 

    /** 
    * Returns the number of items in the cursor 
    * 
    * @return Number of items in the cursor, or 0 if null 
    */ 
    @Override 
    public int getItemCount() { 
     if (mPlaces == null) { 
      Log.d("countcheck", "zero bro"); 
      return 0; 
     } 
     return mPlaces.getCount(); 

    } 


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

    @Override 
    public void onStatusChanged(String s, int i, Bundle bundle) { 

    } 

    @Override 
    public void onProviderEnabled(String s) { 

    } 

    @Override 
    public void onProviderDisabled(String s) { 

    } 



    /** 
    * PlaceViewHolder class for the recycler view item 
    */ 
    class PlaceViewHolder extends RecyclerView.ViewHolder { 

     TextView nameTextView; 
     TextView addressTextView; 
     TextView taskTextView; 

     public PlaceViewHolder(View itemView) { 
      super(itemView); 
      nameTextView = (TextView) itemView.findViewById(R.id.name_text_view); 
      addressTextView = (TextView) itemView.findViewById(R.id.address_text_view); 
      taskTextView = (TextView) itemView.findViewById(R.id.task_text_view); 
     } 

    } 

} 

答えて

1

onBindViewHolderが呼び出されたときに、updatedLocがまだnullの場合、ロケーションプロバイダはまだロケーションを受信して​​いないことを意味します。

あなたは

if(updatedLoc != null){ 
    float distance = updatedLoc.distanceTo(des); 
    distance = distance/1000; 
    dist = ""; 

    if (distance < 1) { 
     dist = "less than km away"; 
    } else { 
     dist = String.format("%.2f", distance) + " km"; 
    } 
} else { 
    dist = "Waiting for location..."; 
} 

holder.nameTextView.setText(placeName); 
holder.addressTextView.setText(dist); 

以下のようなヌルの場合と反対onBindViewHolderupdatedLocをラップする必要があり、あなたが場所を受信するたびに、onBindViewHolderあなたはので、代わりにWaiting for location...

の距離を計算し、表示するために再び呼び出さなければなりませんcreateLocationCallbackメソッドを更新する必要があります。ただ、あなたはグローバルなものにonBindViewHolderからホルダーを割り当て、グローバル変数にホルダーを取る、と言って、その後、コールバックの内側にそれを使用しているnotifyDataSetChanged()

private void createLocationCallback() { 
    mLocationCallback = new LocationCallback() { 
     @Override 
     public void onLocationResult(LocationResult locationResult) { 
      super.onLocationResult(locationResult); 

      updatedLoc = locationResult.getLastLocation(); 

      Log.d("testingvalue",String.valueOf(updatedLoc==null)); 
      //mLastUpdateTime = DateFormat.getTimeInstance().format(new Date()); 

      notifyDataSetChanged(); 
     } 
    }; 
} 
+0

正確に何が必要なのですか、解決しました! – user3820753

0

コールバックにnotifyDataSetChanged()が表示されません。 追加してください。

+0

を追加し、その後のTextViewするテキストを設定し、notifyDataSetChanged()? – user3820753

+0

nope。コールバックの中で 'PlaceListAdapter.this.notifyDataSetChanged()'を使うことを意味します。 – Vyacheslav

+0

申し訳ありませんが、最新のNPEの問題を解決する方法がわかりません – user3820753

関連する問題