【发布时间】:2017-12-28 07:05:45
【问题描述】:
这是我第一次在 Android 中使用 Google Maps。我能够创建显示one marker 的地图。这对我来说是一个好的开始。但是,我想显示multiple markers。为此,我使用volley 从数据库中获取位置。但是,我遇到了一个问题,一个我以前遇到过的问题,但是我设法解决了这个问题,现在它在我当前的项目中再次浮出水面,即我喜欢在我的应用程序中使用Singletons 来存储数据,只要应用程序在内存中。例如,我的singleton 可以保存array list of objects,我可以在任何活动/片段中随时随地获取数组列表。但是,我需要在activity/fragment 变为活动状态之前在我的singleton 中填充arraylist 并访问onCreate/onCreateView 中的对象的arraylist,但似乎activity/fragment 加载速度非常快并且对@987654334 的引用来自singleton 的@ 始终是null。在我目前的项目中:
这是处理所有位置的singleton class
public class PointOfInterestLab {
private ArrayList<PointOfInterest> mPointOfInterests;
private static PointOfInterestLab sPointOfInterestLab;
private Context mAppContext;
private PointOfInterestLab(Context appContext){
mAppContext = appContext;
mPointOfInterests = new ArrayList<PointOfInterest>();
}
public static PointOfInterestLab get(Context c){
if(sPointOfInterestLab == null){
sPointOfInterestLab = new PointOfInterestLab(c.getApplicationContext());
}
return sPointOfInterestLab;
}
public ArrayList<PointOfInterest> getPointOfInterests(){
return mPointOfInterests;
}
public PointOfInterest getPointOfInterest(int id){
for(PointOfInterest pointOfInterest: mPointOfInterests){
if(pointOfInterest.getID() == id){
return pointOfInterest;
}
}
return null;
}
public void addPointOfInterest(PointOfInterest pointOfInterest){
mPointOfInterests.add(pointOfInterest);
}
public void clearPointOfInterests(){
mPointOfInterests.clear();
}
public void deletePointOfInterest(PointOfInterest pointOfInterest){
mPointOfInterests.remove(pointOfInterest);
}
}
在我要显示位置的片段中:
public class PointOfInterestMapFragment extends Fragment implements OnMapReadyCallback {
private static final String TAG = PointOfInterestMapFragment.class.getSimpleName();
private GoogleMap mGoogleMap;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//get locations from server
getPOISFromDB();
}//end method onCreate
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle saveInstanceState){
View v = inflater.inflate(R.layout.fragment_poi_map, parent, false);
//obtain the support fragment and get notified when the map is ready
SupportMapFragment mapFragment = (SupportMapFragment)getChildFragmentManager()
.findFragmentById(R.id.map);
//pass fragment in getMapAsync handler
mapFragment.getMapAsync(this);
return v;
}//end method onCreateView
@Override
public void onMapReady(GoogleMap googleMap){
mGoogleMap = googleMap;
ArrayList<PointOfInterest> pointOfInterests;
pointOfInterests = PointOfInterestLab.get(getActivity())
.getPointOfInterests();
for(PointOfInterest pointOfInterest : pointOfInterests){
//add marker and move camera
/*LatLng location = new LatLng(pointOfInterest.getLocation().getLatitude()
, pointOfInterest.getLocation().getLongitude());
mGoogleMap.addMarker(new MarkerOptions()
.position(location)
.title(pointOfInterest.getName()));
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(location));*/
Log.d(TAG, pointOfInterest.getName());
}
/*This is just for debugging, it is returning a null object
Meaning by the time the array list of the singleton class
is being populated this has been called I guess*/
PointOfInterest pointOfInterest = PointOfInterestLab.get(getActivity()).getPointOfInterest(3);
LatLng location = new LatLng(pointOfInterest.getLocation().getLatitude(),pointOfInterest.getLocation().getLongitude());
mGoogleMap.addMarker(new MarkerOptions()
.position(location)
.title("location"));
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(location));
}
//Get locations from db
private void getPOISFromDB(){
// Tag used to cancel the request
String tag_string_req = "req_poi_list";
StringRequest strReq = new StringRequest(Request.Method.POST,
AppConfig.URL_POI_LIST, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, "Response: " + response);
try {
JSONObject jObj = new JSONObject(response);
JSONArray jsonArray = jObj.getJSONArray("pois");
PointOfInterestLab.get(getActivity()).clearPointOfInterests();
for(int i=0; i < jsonArray.length(); i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
int id = jsonObject.getInt("poi_id");
String name = jsonObject.getString("name");
String summary = jsonObject.getString("summary");
double latitude = jsonObject.getDouble("latitude");
double longitude = jsonObject.getDouble("longitude");
Location location = new Location("dummyProvider");
location.setLatitude(latitude);
location.setLongitude(longitude);
PointOfInterest pointOfInterest = new PointOfInterest(id, name, summary
, location);
PointOfInterestLab.get(getActivity()).addPointOfInterest(pointOfInterest);
}
} catch (JSONException e) {
Log.e(TAG, e.getMessage());
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Server error: " + error.getMessage());
}
}) {
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
SQLiteHandler sqLiteHandler = new SQLiteHandler(getActivity());
User user = sqLiteHandler.getUserDetails();
params.put("user_id", user.getUserID());
return params;
}
};
// Adding request to request queue
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
}//end method getPOISFromDB
}//end class
这是我现在用来测试的部分代码。我在LatLng location = new LatLng(pointOfInterest.getLocation().getLatitude(),pointOfInterest.getLocation().getLongitude()); 在线收到错误PointOfInterest.getLocation()' on a null object reference
/*This is just for debugging, it is returning a null object
Meaning by the time the array list of the singleton class
is being populated this has been called I guess*/
PointOfInterest pointOfInterest = PointOfInterestLab.get(getActivity()).getPointOfInterest(3);
LatLng location = new LatLng(pointOfInterest.getLocation().getLatitude(),pointOfInterest.getLocation().getLongitude());
mGoogleMap.addMarker(new MarkerOptions()
.position(location)
.title("location"));
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(location));
我也尝试在托管活动的onCreate 方法中调用数据库api,但似乎不起作用
public class MainActivity extends AppCompatActivity {
......
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pedometer);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
User user = new User();
user.checkLogin(MainActivity.this);
tabLayout = (TabLayout)findViewById(R.id.tabs);
viewPager = (ViewPager)findViewById(R.id.viewpager);
viewPager.setAdapter(new MyAdapter(getSupportFragmentManager()));
viewPager.setOffscreenPageLimit(2);
//runnable to get rid of bug
tabLayout.post(new Runnable() {
@Override
public void run() {
tabLayout.setupWithViewPager(viewPager);
}
});
setTitle("Updates");
//get locations from db
getPOISFromDB();
}//end method onCreate
private class MyAdapter extends FragmentStatePagerAdapter {
private MyAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position)
{
switch (position){
case 0 :
return new FirstFragment();
case 1 :
eturn new SecondFragment();
case 2 :
return new PointOfInterestMapFragment();
}
return null;
}
@Override
public int getCount() {
return 3;
}
/**
* This method returns the title of the tab according to the position.
*/
@Override
public CharSequence getPageTitle(int position) {
switch (position){
case 0 :
return getResources().getString(R.string.fragment_1);
case 1 :
return getResources().getString(R.string.fragment_2);
case 2 :
return getResources().getString(R.string.fragment_3);
}
return null;
}
}//end class MyAdapter
private void getPOISFromDB(){
// Tag used to cancel the request
String tag_string_req = "req_poi_list";
StringRequest strReq = new StringRequest(Request.Method.POST,
AppConfig.URL_POI_LIST, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, "Response: " + response);
try {
JSONObject jObj = new JSONObject(response);
JSONArray jsonArray = jObj.getJSONArray("pois");
PointOfInterestLab.get(AppController.getInstance()).clearPointOfInterests();
for(int i=0; i < jsonArray.length(); i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
int id = jsonObject.getInt("poi_id");
String name = jsonObject.getString("name");
String summary = jsonObject.getString("summary");
double latitude = jsonObject.getDouble("latitude");
double longitude = jsonObject.getDouble("longitude");
Location location = new Location("dummyProvider");
location.setLatitude(latitude);
location.setLongitude(longitude);
PointOfInterest pointOfInterest = new PointOfInterest(id, name, summary
, location);
PointOfInterestLab.get(AppController.getInstance()).addPointOfInterest(pointOfInterest);
}
} catch (JSONException e) {
Log.e(TAG, e.getMessage());
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Server error: " + error.getMessage());
}
}) {
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
SQLiteHandler sqLiteHandler = new SQLiteHandler(AppController.getInstance());
User user = sqLiteHandler.getUserDetails();
params.put("user_id", user.getUserID());
return params;
}
};
// Adding request to request queue
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
}//end method getPOISFromDB
}
如何在 onMapReady 方法中显示标记,即在 onMapReady 方法执行之前填充单例?
【问题讨论】:
-
你可以在activity中调用数据库api调用并存储在我们的singleton类中。之后你就可以启动fragment了。否则在片段中调用 api,然后在获取数据时初始化地图。
-
创建一个在 googleMap 对象上创建标记的函数。因此,在获得成功响应后,您可以创建此功能编号。您的对象具有 LatLong 的时间
-
@Soham 在活动的 onCreate 方法中还是?
-
是的,
onCreate。 @促进者。 -
在得到 api 的响应后设置你的适配器
viewPager.setAdapter(new MyAdapter(getSupportFragmentManager()));。您正在初始化适配器,这就是您收到空指针异常的原因。
标签: android google-maps android-fragments android-volley