ParseObject subclass cannot make changes in constructor - android

I have a ParseObject subclass with a constructor that tries to set a field with a new UUID:
#ParseClassName("Results")
public class Results extends ParseObject {
public static final String FIELD_UUID = "uuid";
public Results() {
// Default constructor
setUuid();
}
public String getUuid() {
return getString(FIELD_UUID);
}
public void setUuid() {
UUID uuid = UUID.randomUUID();
put(FIELD_UUID, uuid.toString());
}
...
}
However, apparently I cannot call setUuid() in the constructor as the follow error occurs:
java.lang.IllegalStateException: A ParseObject subclass default constructor must not make changes to the object that cause it to be dirty.
I'd prefer to have the UUID set automatically every time a new Results object is created instead of creating a new object, then calling setUuid(). Is this possible to do, or is there a workaround?

Pointers is definitely the way to go.
The best mehod I have found is to use EventBus to pass whole ParseObjects, you will find an example in my answer to this question: Getting Parse Object ID from onListItemClick
It is really simple and saves you the trouble of doing extra queries to locate the passed object.

Related

Android create static ArrayList

im trying to remove values from an arrayList im my android app, but they keep re-appearing.
My arrayList is in a separate class,
in my Main Activty I create an instance of that class and remove a value from the array.
I exit the Main Activity and return the value re-appears.
My Question is how can I can some kind of static instance of the array class???
//ArrayClass
public class ArrayClass {
public final static ArrayList<String> words = new ArrayList<String>();
public ArrayClass() {
words.add("WORD");
words.add("WORD");
words.add("WORD");
}
//Main Class
ArrayClass wordc = new ArrayClass();
#Override
protected void onCreate(Bundle savedInstanceState) {
wordc.removeWord(0);
}
Orest is correct you do want a singleton pattern, but remember when you access the class's methods you always need to use the getInstance() method.
For example a method within the Class:
public String getWord(index i) {
.......
}
Should be called statically as follows
ArrayClass.getInstance().getWord(i);
NOT like this
wordc.getWord(i);
This guarantees that there is one and only one instance (thus the singleton)
I might be confused on what you are doing but to access the static Array you don't want to create an instance of the class. Everytime you do that you are running the constructor which, in the example code, populates your static Array each time with 3 values.
I don't see exactly what you are trying to accomplish so maybe you could explain that a little better but I'm guessing this really isn't what you want your constructor doing. I think you want to access the Array itself statically
//Main Class
ArrayClass wordc = new ArrayClass();
#Override
protected void onCreate(Bundle savedInstanceState) {
wordc.removeWord(0); //don't need this
ArrayClass.words.remove(0); // would remove the element at index 0
}
But this still wouldn't solve your problem. You need a method inside your ArrayClass class that adds items to your Array. Doing it in your constructor will add these items each time you create a new instance of your class.
If this doesn't answer your question then maybe you can explain your assignment a little better.
Have you tried the Singleton patter? You will have one static reference of ArrayClass and it's internal state won't be violated by activity lifecycle.
public class ArrayClass {
private static ArrayClass instance;
public static ArrayClass getInstance() {
if(instance == null) instance = new ArrayClass();
return instance;
}
//...rest goes as is.

Using Gson to deserialise Json into a singleton

I'm using Gson to deserialise Json into a model ApplicationModel. I want this Model to be a singleton so I can access it elsewhere in my application.
Now as Gson creates an instance of this class, I'm creating the singleton instance in a rather unconventional way. See below:
public class ApplicationModel {
private static ApplicationModel instance;
private GeneralVO general;
protected ApplicationModel() {
instance = this;
}
public static ApplicationModel getInstance() {
return instance;
}
public String getVersionDate() {
return general.getVersionDate();
}
}
This is the way I create it and then reuse it later in the application:
InputStreamReader reader = new InputStreamReader(is);
ApplicationModel model1 = new Gson().fromJson(reader,ApplicationModel.class);
Log.i("MYTAG", "InputStream1 = "+model1.toString());
Log.i("MYTAG", "Date: "+model1.getVersionDate());
ApplicationModel model2 = ApplicationModel.getInstance();
Log.i("MYTAG", "InputStream1 = "+model2.toString());
Log.i("MYTAG", "Date: "+model2.getVersionDate());
This works as the getInstance() returns the same model but somehow this just doesn't seem right.
My question is 'is this a good way of going about it or is there a better solution???'
EDIT
A much better way of doing singletons is to use an enum with one INSTANCE element.
See this post for an explanation
I suggest to instantiate your singleton instance on your Model, rather than instantiating it using constructor.
public class ApplicationModel {
private static ApplicationModel instance; //= new ApplicationModel();
//instantiating here is called an "Eagerly Instantiated"
private GeneralVO general;
private ApplicationModel() {
}
public static ApplicationModel getInstance() {
//instantiating here is called "Lazily Instantiated", using :
//if (instance==null) { --> Check whether 'instance' is instantiated, or null
// instance = new ApplicationModel(); --> Instantiate if null
//}
return instance; //return the single static instance
}
public String getVersionDate() {
return general.getVersionDate();
}
}
By setting the constructor to private, you prevent the object from being re-instantiated by another class, to use the object, you will have to call the object with ApplicationModel.getInstance().
So if you want to set values, call ApplicationModel.getInstance().setterMethod(value), Why this is useful? if you want to track the change, you will only need to track the setter method. If you used constructors, you will have to track the constructors too.
Example :
// To SET the value:
// instead of ApplicationModel model1 = new Gson().fromJson(reader,ApplicationModel.class);
ApplicationModel.getInstance.setValue(new Gson().fromJson(reader,ApplicationModel.class);
// To GET the value :
ApplicationModel.getInstance.getValue();
The "Eager Instantiation" vs "Lazy Instantiation" :
Eager Instantiation is useful if you want an easy way to deal with
Threads
Lazy Instantiation has better memory footprints
There's more than that, you can google it for more info, but I think this should be enough for you right now.
Hope this helps, and good luck ^^
Regards,
Reid

Error while trying to execute Sugar database CRUD operation

I (having mediocre developing skills) actually try to use Sugar as a database wrapper for my android project.
Therefore, I was following along the "Getting-Started-Guide" (http://satyan.github.io/sugar/getting-started.html) to get ready as soon as possible.
I created a class for my entities, called DataSet.java :
import com.orm.SugarRecord;
public class DataSet extends SugarRecord{
int someData;
double evenMoreData;
public DataSet(Context ctx){
super(ctx);
}
public DataSet(Context ctx,
int someData,
long evenMoreData) {
super(ctx);
this.someData = someData;
this.evenMoreData = evenMoreData;
}
}
I call the class in the following way:
someGreatClass something;
someMoreGreatCode somemore;
DataSet dataSet = new DataSet(
ctx, // Here Eclipse throws the error
something.method(),
somemore.anothermethod());
DataSet.save();
When I try to build this and to push it onto my device, Eclipse refuses to compile and throws this error:
ctx cannot be resolved to a variable
Considering the fact that I'm relatively new to Android development, the error may be obvious and I hope to get a tip how to solve this.
P.S.: Furthermore, I don't fully get the developer's statement in the getting-started-Note:
Please retain one constructor with Context argument. (This constraint will be removed in subsequent release.)
Thank you very much!
// Edit: Did edit the class name from LocationDataSet to Data set for clarification
First of all, the getting-started-note tells you that you need a constructor with only a context parameter, you did this here so that's ok
public DataSet(Context ctx){
super(ctx);
}
about
ctx cannot be resolved to a variable
I think you don't have a variable called ctx, I don't know if you're familiar with android context? (basically a context is a service or an activity), if you're using this code in an activity or a service, just use the 'this' keyword and not the ctx variable
The code you provide doesn't really show what you're doing, but you showed us the code from 'DataSet', but the error happens with a LocationDataSet? And you're calling save on DataSet?
The save method must be called on an object, not a class.
Also don't forget that sugar needs the special application class in the manifest
UPDATE with example:
Your dataset class (the sugarrecord) should look like this, that's ok in your code as far as I can see
public class DataSet extends SugarRecord<DataSet>{
private String someData;
public DataSet(Context c){
super(c);
}
public DataSet(Context c, String someData){
super(c);
this.someData = someData;
}
}
An activity that uses the record should look like this
public class SomeActivity extends Activity {
public void someMethodThatUsesDataSet(){
// Create a dataset object with some data you want the save and a context
// The context we use here is 'this', this is the current instance of SomeActivity,
// you absolutely need this, I think this is what you're doing wrong,
// you can't use ctx here because that's not a known variable at this point
DataSet example = new DataSet(this, "data you want to save");
// Tell Sugar to save this record in the database
example.save();
}
}

What is the data type of 'MyActivity.this' - Android

well my question is that there aren't pointers in JAVA ...
but when we have to start another activity we do like this :
Intent in = new Intent(MyActivity.this, NewActivity.class);
startAcitivity(in);
So my question is that what is the data type of MyActivity.this ??
In java pointers are not explicitly allowed,
However passing by reference(object) in Java is something which is implicitly based on pointer concept.
In your case, you are passing the context of parent class to child class,
which is actually passing by reference concept.
Hope this helps.
Writing MyActivity.this is the same as writing this, if you are in a non-nested class, or to top-level class.
See this example:
public class TopLevel{
public static void main(String[] args){
new TopLevel().printClass();
}
public TopLevel(){
new LowerLevel().printClass();
}
public void printClass(){
System.out.println("Outer Class: ");
// Will print something like "TopLevel.class"
System.out.println(this.getClass());
}
public class LowerLevel{
// This is a Nested-Class.
public void printClass(){
System.out.println("Nested Class: ");
// Will print "TopLevel$LowerLevel.class"
System.out.println(this.getClass());
// Will print "TopLevel.class" again
System.out.println(TopLevel.this.getClass());
}
}
}
Some using this in the nested-class does not reference to the same instance as when using it in the top-level class. Therefor, to get the "context" of the outer class in your nested class, you also specify the class you want the this-context from.

when is an object created and can be referenced to?

I have a simple question but can't find the solution in the references anywhere.
When I create an instance of a certain class where the instance is to be propagated to a couple of places everytime it is created again the most obvious place where to put the code is in the creation method of the instance itself. This is how it would look like:
public void MYTest() {
public MYTEST() {
ANOTHER_CLASS.myTest = this; // <-------- can I already use the new this and assign it ?
}
}
Can I put the assignments of this just newly created instance to other variables already in the creation method or do I have to write an extra "super" creation method like this and put this also in MYTEST:
public void MYTest() {
public MYTEST() {
ANOTHER_CLASS.myTest = this; // <-------- can I already use the new this and assign it ?
}
public static MYTEST superCreationMethodForMYTEST() {
x = new MYTEST(); // <- here for sure the creation of MYTEST instance is finished BEFORE the assgnment happens
ANOTHER_ClASS.myTest = x;
.... all the other assignments for x.....
}
}
and then call it like
x = MYTEST.superCreationMethodForMYTEST();
instead of:
x = new MYTEST();
Thanks
You can assign the this reference anywhere in the constructor. However, it may not be wise, depending on your situation. The main problem is that while the object exists at the time of the constructor, it is not completely constructed and therefore may not be in a state to handle method calls correctly. If the assigned reference is used by an unsuspecting thread, for example, (or by a method called by your constructor) before your constructor (and any subclass constructors) finish, bad things may happen.
Edited to add: Your problem, as I understand it, is to make sure that a reference to the object is stored in particular places before whoever requested the creation of the object receives the newly created object. One common pattern is to do basically what you surmise in your question, namely having a factory method (a static method) that uses new to construct the object and then stores it in the appropriate places. This ensures that only references to a fully constructed object is stored. At the same time, the actual constructor is declared private or protected to prevent accidental use of new outside the factory method.

Categories

Resources