I tried to save this object using Realm But I got this error
Error:(24, 9) error: Type
java.util.ArrayList of field
savedPath is not supported
Here is my code :
public class TrackingInfo extends RealmObject {
private int order_id;
private double savedDistance;
private double savedDuration;
private ArrayList <LatLng>savedPath;
public int getOrder_id() {
return order_id;
}
public void setOrder_id(int order_id) {
this.order_id = order_id;
}
public double getSavedDistance() {
return savedDistance;
}
public void setSavedDistance(double savedDistance) {
this.savedDistance = savedDistance;
}
public double getSavedDuration() {
return savedDuration;
}
public void setSavedDuration(double savedDuration) {
this.savedDuration = savedDuration;
}
public ArrayList<LatLng> getSavedPath() {
return savedPath;
}
public void setSavedPath(ArrayList<LatLng> savedPath) {
this.savedPath = savedPath;
}
public TrackingInfo(){}}
Thanx in advance
Both List and LatLng cannot be stored in Realm directly. You will need to create a model object for LatLng and then use a RealmList object containing your model objects.
public class Location extends RealmObject {
public Location() { }
double latitude;
double longitude;
}
RealmList<Location> savedPath = new RealmList<Location>();
//Add location objects to savedPath and store it in your TrackingInfo object
You will need to manually convert objects of the LatLng class to the Location class when you are inserting/retrieving from the database.
Related
I have a Linked List in one activity (A) that I want to share with another Activity (B).
The list contains a username of type string and contains coordinates of type LatLng. I am also using Intent and bundle to share data between activities. I tried using Parcelable but unable to figure out how to use it. Here is the code I have:
data.java
public class data implements Parcelable{
private LatLng coordinates;
private String name;
public data() {
name = null;
coordinates = null;
}
public data(String name, LatLng coordinates)
{
this.name = name;
this.coordinates = coordinates;
}
public data(Parcel in) {
coordinates = in.readParcelable(LatLng.class.getClassLoader());
name = in.readString();
}
public static final Creator<data> CREATOR = new Creator<data>() {
#Override
public data createFromParcel(Parcel in) {
return new data(in);
}
#Override
public data[] newArray(int size) {
return new data[size];
}
};
public LatLng getLatLng () {
return coordinates;
}
#Override
public int describeContents() {
return hashCode();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeParcelable(coordinates, flags);
}
}
Activity A
public class A extends FragmentActivity implements
OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
GoogleMap.OnMyLocationButtonClickListener,
ActivityCompat.OnRequestPermissionsResultCallback {
Button switchToSeek;
double mLatitude;
double mLongitude;
LinkedList<data> storedData = new LinkedList<>();
protected void onCreate(Bundle savedInstanceState) {
...
switchToSeek.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getCurrentLocation();
Intent intent = new Intent(A.this, B.class);
Bundle xy = new Bundle();
xy.putDouble("x", mLatitude);
xy.putDouble("y", mLongitude);
xy.putParcelable("list", storedData); <---------- error: wrong second arugment
intent.putExtra("xy", xy);
A.this.startActivity(intent);
}
});
Activity B
public class B extends FragmentActivity implements OnMapReadyCallback {
double mLatitude;
double mLongitude;
LatLng current;
GoogleMap gMap;
LinkedList <data> copyData = new LinkedList<>();
#Override
public void onMapReady(GoogleMap googleMap) {
gMap = googleMap;
...
Intent intent = getIntent();
Bundle xy = intent.getBundleExtra("xy");
if (xy != null) {
mLatitude = xy.getDouble("x");
mLongitude = xy.getDouble("y");
}
/***** Call linked list here and set equal to copyData *****/
current = new LatLng(mLatitude, mLongitude);
gMap.moveCamera(CameraUpdateFactory.newLatLngZoom(current, 18.0f));
}
There is no easy way to do that, since LinkedList does not implement serializable or parcelable.
You CAN implement your own linked list class and make it a serializable/parcelable object which can then be passed.
Or you can convert its content into another data type such as an array and then recreate the linkedlist.* THIS IS HIGHLY INEFFICIENT
I believe there are other ways but this is a standard problem in android dev. Maybe try using fragments if possible and passing the linkedlist through a setter()
If the list is not huge, you can do it using the following helper class:
public class ParcelableLinkedList<E extends Parcelable> implements Parcelable {
private final LinkedList<E> linkedList;
public final Creator<ParcelableLinkedList> CREATOR = new Creator<ParcelableLinkedList>() {
#Override
public ParcelableLinkedList createFromParcel(Parcel in) {
return new ParcelableLinkedList(in);
}
#Override
public ParcelableLinkedList[] newArray(int size) {
return new ParcelableLinkedList[size];
}
};
public ParcelableLinkedList(Parcel in) {
// Read size of list
int size = in.readInt();
// Read the list
linkedList = new LinkedList<E>();
for (int i = 0; i < size; i++) {
linkedList.add((E)in.readParcelable(ParcelableLinkedList.class.getClassLoader()));
}
}
public ParcelableLinkedList(LinkedList<E> linkedList) {
this.linkedList = linkedList;
}
LinkedList<E> getLinkedList() {
return linkedList;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int flags) {
// Write size of the list
parcel.writeInt(linkedList.size());
// Write the list
for (E entry : linkedList) {
parcel.writeParcelable(entry, flags);
}
}
}
In your onClick() method, add the data to the Bundle like this:
xy.putParcelable("list", new ParcelableLinkedList<data>(storedData));
To extract the data from the Bundle, do this:
copyData = ((ParcelableLinkedList<data>)xy.getParcelable("list")).getLinkedList();
I haven't actually compiled and tested this code, but it should work.
If the list is really huge, you are better off storing it in a static member variable in one class and then just referencing it from the other. This isn't normally the way you want to do things in Android, but it is sometimes more expedient to do this than to serialize and deserialize a huge amount of data just to pass it between 2 activities that have access to the same memory space.
I am currently trying to add a RealmObject to RealmList inside another RealmObject.
So this is the way I am doing it at the moment.
First I create and save a RealmObject called "RouteRealm" like this:
public void insertNewRoute(int routeId, long routeDate) {
realm.beginTransaction();
RouteRealm routeRealm = realm.createObject(RouteRealm.class);
routeRealm.setId(routeId);
routeRealm.setDate(routeDate);
realm.commitTransaction();
}
The class RealmObject looks like this:
public class RouteRealm extends RealmObject {
#PrimaryKey
private int id;
private long date;
private RealmList<RoutePointRealm> routePoints;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public long getDate() {
return date;
}
public void setDate(long date) {
this.date = date;
}
public RealmList<RoutePointRealm> getRoutePoints() {
return routePoints;
}
public void setRoutePoints(RealmList<RoutePointRealm> routePoints) {
this.routePoints = routePoints;
}
}
The above works. The problem occurs when I try to add a RoutePointRealm to the list called routePoints. Here is my code for adding the RoutePointRealm object to the list:
public void insertNewRoutePoint(int routeId, String address, float latitude, float longitude, long routePointId, long routePointTime) {
realm.beginTransaction();
RouteRealm routeRealm = realm.where(RouteRealm.class).equalTo("id", routeId).findFirst();
RoutePointRealm routePointRealm = realm.createObject(RoutePointRealm.class);
routePointRealm.setAddress(address);
routePointRealm.setLatitude(latitude);
routePointRealm.setLongitude(longitude);
routePointRealm.setRoutePointID(routePointId);
routePointRealm.setRoutepointTime(routePointTime);
routeRealm.getRoutePoints().add(routePointRealm);
realm.copyToRealmOrUpdate(routeRealm);
realm.commitTransaction();
}
And the RoutePointRealm looks like this:
public class RoutePointRealm extends RealmObject {
#PrimaryKey
private long routePointID;
private float longitude, latitude;
private long routepointTime;
private String address;
public long getRoutePointID() {
return routePointID;
}
public void setRoutePointID(long routePointID) {
this.routePointID = routePointID;
}
public float getLongitude() {
return longitude;
}
public void setLongitude(float longitude) {
this.longitude = longitude;
}
public float getLatitude() {
return latitude;
}
public void setLatitude(float latitude) {
this.latitude = latitude;
}
public long getRoutepointTime() {
return routepointTime;
}
public void setRoutepointTime(long routepointTime) {
this.routepointTime = routepointTime;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
For some reason, the RoutePointRealm are added to the list, but all of its fields are set to zero and null. I have debugged my app to make sure that all of the parameters contains the correct values with the right datatypes etc. So now I know that the problem is related to the Realm methods.
What am I doing wrong?
First of all, thank you for your answers! I still couldn't get it to work after changing the solutions you've proposed. At least I didn't think so.
The reason I thought it didn't work, was partly because of a mistake that I made with my gui showing a zero value.. This made me to go into debugging the app, but apparently the debugger always shows zero or null values for the Realm objects.. At least in my case.
So at last, I tried making a Toast message with a fetched value from Realm and it returned what it was supposed to.
So I don't think that there were any problems to begin with.. The debugger just got me thinking so. I am sorry if I wasted your time, but I still thought that I should post this as an answer if other were to encounter the same problem.
All your objects are managed by Realm, so you don't need the realm.copyToRealmOrUpdate(routeRealm); call.
the problem comes from ID, Realm not support auto increment behaviour so you should do it manually.
something like :
beginTransaction()
foo.setId(value)
commitTrasaction()
My personal recommendation:
public void insertNewRoute(final int routeId, final long routeDate) {
final RouteRealm routeRealm = new RouteRealm();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
routeRealm.setId(routeId);
routeRealm.setDate(routeDate);
realm.insertOrUpdate(routeRealm);
}
});
}
public void insertNewRoutePoint(final int routeId, final String address, final float latitude,
final float longitude, final long routePointId, final long routePointTime) {
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
RouteRealm routeRealm = realm.where(RouteRealm.class).equalTo(RouteRealmFields.ID, routeId).findFirst();
RoutePointRealm routePointRealm = new RoutePointRealm();
routePointRealm.setAddress(address);
routePointRealm.setLatitude(latitude);
routePointRealm.setLongitude(longitude);
routePointRealm.setRoutePointID(routePointId);
routePointRealm.setRoutepointTime(routePointTime);
routePointRealm = realm.copyToRealmOrUpdate(routePointRealm);
routeRealm.getRoutePoints().add(routePointRealm);
}
});
}
I am trying to get the onPostExecute() method invoked after finishing the doInBackground() method and then passed the custom arrayList<ItemDTO> to the Map activity but onPostExecute method is not being invoked. I am not getting any Output in the Logcat as asign that it was invoked. How can I fix it?
I have debugged it and I can see the data in the ArrayList data object.
I appreciate any help.
GetLLRD class
public class GetLLRD {
Context mContext;
public void post_selected(String json, Context context) {
new MyAsyncTask().execute(json);
context = this.mContext;
}
class MyAsyncTask extends AsyncTask<String, Integer, List<ItemDTO>> {
#Override
protected List<ItemDTO> doInBackground(String... params) {
.
.
.
.
Gson gson = new Gson();
Type listType = new TypeToken<List<ItemDTO>>() {
}.getType();
ArrayList<ItemDTO> data = gson.fromJson(sb.toString(), listType);
.
.
.
.
return data;
}
protected void onPostExecute(ArrayList<ItemDTO> result) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
new MyAsyncTask().execute();
System.out.println("The method onPostExcute() in GETLLRD class was invoked again");
}
}, 1*30 * 1000);
if (result != null) {
Intent intent = new Intent(mContext, Map.class);
intent.putExtra("list",result);
mContext.startActivity(intent);
}else{
Log.e("123", "Avoiding null pointer, the dat is null in the GETLLRD class!!!");
}
}
}
}
MapDataJSON class with the inner class ItemDTo which I need to get the data from the JSON string that I am getting from the Server.
public class MapDataJSON {
ArrayList<ItemDTO> items;
public MapDataJSON(ArrayList<ItemDTO> items) {
super();
this.items = items;
}
public ArrayList<ItemDTO> getItems() {
return items;
}
public void setItems(ArrayList<ItemDTO> items) {
this.items = items;
}
public static class ItemDTO implements Serializable {
private static final long serialVersionUID = 1L;
double latitude;
double longitude;
int route;
String direction;
public ItemDTO(double latitude, double longitude, int route,
String direction) {
super();
this.latitude = latitude;
this.longitude = longitude;
this.route = route;
this.direction = direction;
}
public double getLatitude() {
return latitude;
}
public double getLongitude() {
return longitude;
}
public int getRoute() {
return route;
}
public String getDirection() {
return direction;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public void setRoute(int route) {
this.route = route;
}
public void setDirection(String direction) {
this.direction = direction;
}
}
}
Your not actually overriding the correct method signature of AsyncTask
it should be
protected void onPostExecute(List<ItemDTO> result)
by specifying ArrayList you're changing the method signature. This is why it's useful to use the Override annotation as your ide or compiler will tell you the method signature doesn't match.
What Im trying to achieve is display points on a map using postcode. I found a script that does this for one postcode, but I would like to display a few at once. So I was thinking of changing the code around a little so the map was created in the first class.
My question is, how do I transfer the values of Class B to Class A?
2 values 'lng' and 'lat' need to be an array
My full code is here if that makes more sense http://pastebin.com/L6tcuPW9
Any help would be great
Class A extents FragmentActivity
{
}
This class gets retrieves the lng and lat values
Class B
{
public static double[] lat;
public static double[] lng;
public void retrievePost( String post)
{
// does a search and retrieves lng and lat
setLat(lat);
setLng(lng);
}
public static void setLat(double lat2)
{
// How do I get this value back into Class A
}
public static void setLng(double lng2)
{
// How do I get this value back into Class A
}
}
Try this:
public interface MyInterface {
public void setLat(double lat);
public void setLng(double lng);
}
class A extends FragmentActivity implements MyInterface{
#Overwrite
public void setLat(double lat) {
//Do Something
}
#Overwrite
public void setLng(double lng){
//Do Something
}
}
Class B
{
private MyInterface interface;
public B(MyInterface interface){
this.interface = interface;
}
public void retrievePost( String post){
interface.setLat(lat);
interface.setLng(lng);
}
}
i have the following class which i intent to pass from one activity to another:
public class Ad extends ListItem implements parcelable{
private String _type;
private String _recordID;
private String _line1;
private String _line2;
private String _line3;
private String _line4;
private String _url;
private IOnUiNeedToUpdateListener _listener;
private boolean _notActive = false;
private String _alertText;
private Double _longitude;
private Double _latitude;
}
i want to pass an array of such objects from one activity to another. however, i do not need to pass all fields.
is it possible to create a parcel only from the desired fields and send it?
It's your code that writes to Parcel and your code that reads from Parcel. So basically yes. You can write whatever you want. Content of all members, content of some, no members, but other values you use to restore state of the object etc, etc.
Try design your class like this..
public class Form implements Parcelable {
private String formdata1;
private String formdata2;
private String formdata3;
private String formdata4;
public Form() {
}
public Form(Parcel in) {
setFormdata1(in.readString());
setFormdata2(in.readString());
setFormdata3(in.readString());
setFormdata4(in.readString());
}
public String getFormdata1() {
return formdata1;
}
public void setFormdata1(String formdata1) {
this.formdata1 = formdata1;
}
public String getFormdata2() {
return formdata2;
}
public void setFormdata2(String formdata2) {
this.formdata2 = formdata2;
}
public String getFormdata3() {
return formdata3;
}
public void setFormdata3(String formdata3) {
this.formdata3 = formdata3;
}
public String getFormdata4() {
return formdata4;
}
public void setFormdata4(String formdata4) {
this.formdata4 = formdata4;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel in, int arg1) {
in.writeString(getFormdata1());
in.writeString(getFormdata2());
in.writeString(getFormdata3());
in.writeString(getFormdata4());
}
public static final Parcelable.Creator<Form> CREATOR = new Parcelable.Creator<Form>() {
#Override
public Form createFromParcel(Parcel in) {
return new Form(in);
}
#Override
public Form[] newArray(int size) {
return new Form[size];
}
};
}