2012-04-29 22 views
1

我正在研究需要向用戶位置顯示最近酒店(例如)的應用程序。一個SQLite數據庫包含所有酒店以及它們的經度和緯度。我搜索並發現,最簡單的方法是在select語句的「Order By」中編寫一個特定的公式。如何通過等式使Select語句成爲Order? (以最短距離訂購)

Cursor cursor = database.query(MySQLiteHelper.TABLE_Hotel, hotelsNames, null, null, null, null, ((lat - Double.valueOf(hotelsLat[0].trim()).doubleValue()) * (lat - Double.valueOf(hotelsLat[0].trim()).doubleValue()) + 
      (lon - Double.valueOf(hotelsLong[0].trim()).doubleValue()) * (lon - Double.valueOf(hotelsLong[0].trim()).doubleValue())); 

注:hotelsLong和hotelsLat都是String []包含從數據庫中經度和緯度。

這是我所做的select語句,問題是有一個錯誤說select語句的參數必須是(String,String [],String,String [],String,String,String),但是什麼我所做的是(字符串,字符串[],NULL,NULL,NULL,NULL,

我應該怎麼辦呢?以及如何按公式結果排序結果?

+0

oehm,兩點之間的直接距離可以比「街道距離」更短,這樣你可能會遇到將用戶送到更遠處的情況。哦,谷歌地圖Api有一個功能,以獲得兩點之間的距離 – CAA 2012-04-29 08:22:51

+0

這可能找到最接近的酒店(絕對值),但不一定是最容易達到的(例如,考慮一個用戶在一邊長而狹窄的湖泊,以及對面的酒店) – 2012-04-29 08:24:23

+0

但是,在這部分,我不想在地圖上顯示我的結果。這個想法是,我喜歡一個搜索頁面,他選擇他想搜索的內容,結果以列表視圖顯示,最近的結果在最上面,最遠的結果在列表的末尾 – MahaK 2012-04-29 08:25:23

回答

0

首先,您的距離計算看起來不正確。請參閱Location類的來源distanceBetween()方法。我建議你使用這個或同一類的distanceTo()

關於要使用的適配器。如果您的數據來自數據庫,則使用CursorAdapter,否則使用BaseAdapter的某些後代。你有兩個選擇。將當前距離保存在sql表中作爲新列(每次接收到新位置或用戶定義要搜索的位置)並按其排序或使用ListViewArrayAdapter

我將描述第二個選項,如果根據用戶的位置和位置顯示酒店應該更平滑,因爲每次接收新位置時都不訪問數據庫,因此更新頻率相當頻繁,但另一方面它消耗更多的內存,因爲酒店存儲爲對象:

創建AsyncTask以獲得Cursor包含酒店。遍歷遊標並填入酒店列表:

@Override 
protected List<Hotel> doInBackground(Void... unused) { 
    final Cursor c = database.query(getting hotels); 
    if (c == null) { 
     return null; 
    } 
    List<Hotel> hotels = new ArrayList<Hotel>(); 
    try { 
     for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) { 
      Hotel hotel = new Hotel(); 
      hotel.fillFromCursor(c); // fills data from cursor 
      hotels.add(hotel); 
     } 
    } finally { 
     c.close(); 
    } 
    return hotels; 
} 

@Override 
protected void onPostExecute(List<Hotels> hotels) { 
    if (hotels != null) { 
     mHotelsAdapter.clear(); 
     for (Hotel h : hotels) { 
      mHotelsAdapter.add(h); 
     } 
     // mLocation is our current location, if we have one, set the distance, see below 
     mHotelsAdapter.updateDistance(mLocation); 
    } 
} 

mHotelsAdapter是適用於您的ListView的適配器。適配器包含updateDistance()方法,應在每次更改所需位置時調用該方法(如位於LocationListener的onLocationChanged(Location location)中)。該方法更新距離並對項目進行排序。

mHotelsAdapter = new HotelAdapter(this); 
getListView().setAdapter(mHotelsAdapter); 
... 

public class HotelsAdapter extends ArrayAdapter<Hotel> { 
    ... 
    public void updateDistance(Location location) { 
     if (location != null) { 
      for (int i = 0; i < getCount(); i++) { 
       Hotel hotel = getItem(i); 
       hotel.setDistance(location); 
      } 
      sort(mComparator); 
      notifyDataSetChanged(); 
     } 
    } 
    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     // implement getView 
    } 

    private static final Comparator<Hotel> mComparator = new Comparator<Hotel>() { 
     @Override 
     public int compare(Hotel lhs, Hotel rhs) { 
      if (lhs.getDistance() > rhs.getDistance()) { 
       return 1; 
      } else if (lhs.getDistance() < rhs.getDistance()) { 
       return -1; 
      } else { 
       return 0; 
      } 
     } 
    }; 
    ... 
} 

最後這裏是Hotel類的setDistance()方法,它設置酒店到作爲參數的位置的距離:

public void setDistance(Location location) { 
    float results[] = new float[1]; 
    Location.distanceBetween(location.getLatitude(), location.getLongitude(), 
     getLatitude(), getLongitude(), results); 
    mDistance = results[0]; 
}