Singleton constructor crashes my app - android

I'm testing out the model layer of my application and I want to add an element to a list. But whenever I try to add some data into my data model the application crashes. I cannot find the reason for this.
My code for the data model.
public class DataModel {
private List<Log> logs;
private static DataModel instance;
private Context ctx;
//Singleton constructor
private DataModel()
{
//This makes it crash
logs.add(new Log("1234","sms", 123545, 1, 0));
//Load logs from database - Not done yet.
}
public static DataModel getInstance()
{
if (instance == null)
{
//Creates the instance
instance = new DataModel();
}
return instance;
}
My code for log
public class Log {
private String phonenumber;
private String type;
private long date;
private int incoming;
private int outgoing;
private long id;
//Constructor for incoming sms or call
public Log( String Phonenumber, String Type, long Date, int Incoming, int Outgoing)
{
this.phonenumber = Phonenumber;
this.type = Type;
this.date = Date;
this.incoming = Incoming;
this.outgoing = Outgoing;
}
public long getId()
{
return id;
}
public void setId(long id)
{
this.id = id;
}
public String getPhonenumber()
{
return phonenumber;
}
public void setPhonenumer(String phonenumber)
{
this.phonenumber = phonenumber;
}
public String getType()
{
return type;
}
public void setType(String type)
{
this.type = type;
}
public long getDate()
{
return date;
}
public void setDate(long date)
{
this.date = date;
}
public int getIncoming()
{
return incoming;
}
public void setIncoming(int incoming)
{
this.incoming = incoming;
}
public int getOutgoing()
{
return outgoing;
}
public void setOutgoing (int outgoing)
{
this.outgoing = outgoing;
}

You are not initializing logs. Its null when you execute this statement:
logs.add(new Log("1234","sms", 123545, 1, 0));
Change:
private List<Log> logs;
to:
private List<Log> logs = new ArrayList<Log>();

I see a context in your code, but you don't set it or use it anywhere so maybe you stripped part of your code. In relation to that, if you use it to UI related stuff (and some other cases) I can guarantee you that it will crash your app if you don't reset it every time the screen orientation changes or you change activities.

You have not Instantiated list object
private List<Log> logs;
Update your constructor to this
//Singleton constructor
private DataModel()
{
//This makes it crash
logs = new ArrayList<Log>();
logs.add(new Log("1234","sms", 123545, 1, 0));
//Load logs from database - Not done yet.
}
Now every time you constructor gets called you will get a fresh copy of list object.

Initialize the List before use
you can initialize the List in Constructor as well
public class DataModel {
private List<Log> logs= new ArrayList<Log>();
private static DataModel instance;
private Context ctx;
//Singleton constructor
private DataModel()
{
//This makes it crash
logs.add(new Log("1234","sms", 123545, 1, 0));
int i=0;
//Load logs from database - Not done yet.
}
public static DataModel getInstance()
{
if (instance == null)
{
//Creates the instance
instance = new DataModel();
}
return instance;
}
}

Don't initialize globally logs and also use synchronized getInstance method so that only one instance should get created if two threads are trying to access at the same time.
Use this code:
public class DataModel {
private List<Log> logs;
private static DataModel instance;
private Context ctx;
//Singleton constructor
private DataModel()
{
if(logs == null){
logs = new ArrayList<Log>();
}
logs.add(new Log("1234","sms", 123545, 1, 0));
//Load logs from database - Not done yet.
}
public synchronized static DataModel getInstance()
{
if (instance == null)
{
//Creates the instance
instance = new DataModel();
}
return instance;
}

Related

Converting the string resources to strings

I've already tried to use
String mystring = getResources().getString(R.string.mystring);
And I found the same theme in this article How can I convert the android resources int to a string. eg.: android.R.string.cancel?. But it doesn't work in my situation.
This is my code:
public class Film{
private int image;
private String name;
private String schedule;
private String description;
public Film() {
}
public int getImage() {
return image;
}
public void setImage(int image) {
this.image = image;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
...
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
public class FilmList {
public static ArrayList<Film> getFilms(){
ArrayList<Film>films=new ArrayList<>();
Film film=null;
film =new Film();
film.setName(getResources().getString(R.string.name1));
film.setImage(R.drawable.img1);
film.setDescription(getResources().getString(R.string.desc1));
films.add(film);
film =new Film();
film.setName(getResources().getString(R.string.name2));
film.setImage(R.drawable.img2);
film.setDescription(getResources().getString(R.string.desc2));
films.add(film);
return films
}
}
If you don't have access to a Context (e.g. via an Activity, Service, ContentProvider, or BroadcastReceiver), you cannot get a string resource.
If you have a class that is not one of the above and it needs to get a string resource, you must either have pass a Context to that class so it can retrieve the resource, or pass that class an already-resolved resource.
Make an application class and add a hold its reference in a static varialble. then you can access context anywhere in the app
public class MyApp extends Application {
private static AppLWP instance;
#Override
public void onCreate() {
super.onCreate();
instance = this;
}
}
Then you can access this instance for context anywhere in the app
public static ArrayList<Film> getFilms(){
ArrayList<Film>films=new ArrayList<>();
Film film=null;
film =new Film();
film.setName(MyApp.instance.getResources()
.getString(R.string.name1));
film.setImage(R.drawable.img1);
film.setDescription(MyApp.instance.getResources()
.getString(R.string.desc1));
films.add(film);
film =new Film();
film.setName(MyApp.instance.getResources()
.getString(R.string.name2));
film.setImage(R.drawable.img2);
film.setDescription(MyApp.instance.getResources()
.getString(R.string.desc2));
films.add(film);
return films
}
}
First, provide context to the class Film via the activity you are calling the object of Film.
If you call from Main Activity you will have to do something like this:
public class MainActivty extends AppCompatActivity {
private static MainActivty obj;
onCreate() {
//usual functions
obj = MainActivity.this;
}
}
Once you have the context, simply try this:
String mystring = context.getString(R.string.mystring);
Or, if you floowed my MainActivty method:
String mystring = MainActivty.obj.getResources().getString(R.string.mystring);

Not receiving data from server using Retrofit 2

I am trying to retrieve Reddit information from a particular subreddit using Retrofit 2. I have followed many tutorials and videos and my code seems to be correct from my perspective but I only manage to have null objects in my model class. I have the permission for internet in the Manifest.
This is a link the JSON I am working with HERE
MainActivity
public class MainActivity extends AppCompatActivity
{
TextView mTextView;
Data mData;
private static final String TAG = "Battlestations";
#Override
protected void onCreate(Bundle savedInstanceState)
{
mTextView = (TextView) findViewById(R.id.test_view);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Call<Data> serviceCall = Service.getDesktopService().desks();
serviceCall.enqueue(new Callback<Data>()
{
#Override
public void onResponse(Call<Data> call, Response<Data> response)
{
Log.d("Reponce","return");
Log.i(TAG, "Response is " + mData.getChildren());
}
#Override
public void onFailure(Call<Data> call, Throwable t)
{
}
});
}
}
Api/Service Class
public class Service
{
private static final String BASE_URL = "https://www.reddit.com/r/";
private static DeskInterface mRetrofit;
public static DeskInterface getDesktopService()
{
if(mRetrofit == null)
{
Retrofit build = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
mRetrofit = build.create(DeskInterface.class);
}
return mRetrofit;
}
public interface DeskInterface
{
#GET("battlestations/hot/.json")
Call<Data> desks();
}
}
Data
public class Data
{
private List<Child> children = null;
public List<Child> getChildren()
{
return children;
}
public void setChildren(List<Child> children)
{
this.children = children;
}
}
Child
public class Child
{
private Data_ data;
public Data_ getData()
{
return data;
}
public void setData(Data_ data)
{
this.data = data;
}
}
Data_
public class Data_
{
private String subreddit;
private Integer score;
private String author;
private String subredditNamePrefixed;
private String url;
private String title;
public String getSubreddit()
{
return subreddit;
}
public void setSubreddit(String subreddit)
{
this.subreddit = subreddit;
}
public Integer getScore()
{
return score;
}
public void setScore(Integer score)
{
this.score = score;
}
public String getAuthor()
{
return author;
}
public void setAuthor(String author)
{
this.author = author;
}
public String getSubredditNamePrefixed()
{
return subredditNamePrefixed;
}
public void setSubredditNamePrefixed(String subredditNamePrefixed)
{
this.subredditNamePrefixed = subredditNamePrefixed;
}
public String getUrl()
{
return url;
}
public void setUrl(String url)
{
this.url = url;
}
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
}
You need to add mData = response.body() in onResponse() (also check response.isSuccessful() first)
The problem is that your Data does not correspond with Reddit JSON. Your Data class
public class Data {
private List<Child> children = null;
}
does not match with the given json, which is:
{
"kind":"listing",
"data":{
"modhash":"...",
"children":[...],
"after":"...",
"before":"..."
}
}
Retrofit automagically convert from json to java but only if the mapping is correct.
A correct Java class would be:
public class Subreddit {
String kind;
Data data;
}
public class Data{
String modhash;
List<Child> children;
String after;
String before;
}
and then modify desks method interface to
Call<Subreddit> desks();
You would have to go recursively for the entire depth of the JSON to get the right mapping.
But before you get to work, just replace your Retrofit interface:
public interface DeskInterface{
#GET("battlestations/hot/.json")
Call<Data> desks();
}
with:
public interface DeskInterface{
#GET("battlestations/hot/.json")
Call<JsonObject> desks();
}
and it should return something. If is still null, then further investigation is needed. If it returns a valid response(some json text) then copy/paste that subreddit to this website where it converts all the json to a valid Java class

Serializable SparseArray<Custom Object>

I want to send my data from Activity1 to Activity2 with putExtra.
My Custom object implements Serializable :
public class ARObjectCategory implements Serializable {
private static final long serialVersionUID = 3128594851129501738L;
public int id;
public String name;
public transient ARObjectCategory parent;
public transient SparseArray<ARObjectCategory> children;
public transient Bitmap iconBitmap = null;
public String icon;
private boolean active = false;
public ARObjectCategory(int id, String name, ARObjectCategory parent) {
this.id = id;
this.name = name;
this.parent = parent;
this.children = new SparseArray<>();
}
public void addChild(ARObjectCategory child) {
children.append(child.id, child);
if (getActive())
child.setActive(true);
}
public final ARObjectCategory getChild(int index) {
return children.valueAt(index);
}
public final SparseArray<ARObjectCategory> getChildren() {
return this.children;
}
public final int getParentLast() {
ARObjectCategory parentTemp = this.parent;
while (parentTemp.parent != null) {
parentTemp = parentTemp.parent;
}
return parentTemp.id;
}
public final ARObjectCategory getChildById(int id) {
return children.get(id, null);
}
public final int getChildrenCount() {
return children.size();
}
public Boolean getActive() {
return this.active;
}
public void setActive(Boolean bool) {
this.active = bool;
}
public Bitmap getIconBitmap() {
return iconBitmap;
}
public void setIconBitmap(Bitmap iconBitmap) {
this.iconBitmap = iconBitmap;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
}
Activity1.java (Sender):
ARObjectCategory test1= adapter.getItem(position);
Intent subCat= new Intent(getActivity(), SubCategoriesActivity.class);
subCat.putExtra("test",test1);
subCat.putExtra("selected",position);
startActivity(subCat);
On Debug Mode my object looks ok. SpraseArray got object of AROjcectCategory.
Activity2.java (Reciever):
Bundle extras = getIntent().getExtras();
if (extras != null) {
int selected = extras.getInt("selected", -1);
ARObjectCategory list = (ARObjectCategory) extras.getSerializable("test");
SparseArray<ARObjectCategory> lista = list.getChildren();
}
But when i debug the Activity2. I see that my SpraseArray of children is null
Finally when i remove the transient from my objects.
public transient ARObjectCategory parent;
public transient SparseArray<ARObjectCategory> children;
I am getting the following error on my logcat :
java.lang.RuntimeException: Parcelable encountered IOException
writing serializable object (name =
com.ethos.ar.core.ARObjectCategory) ........
Caused by:
java.io.NotSerializableException: android.util.SparseArray ......
What is the correct way to send Object that has SpraseArray to other Activity.
Tip: Parcelable is not working:
dest.writeParcelable(this.children);
SparseArray<ARObjectCategory> cannot be converted to SparseArray<Object>
Thanks
When you use the transient modifier, that member is excluded from the serialization process. That's the reason you are getting a null object. When you remove the transient modifier then you receive an exception, but why? That's because the "SparseArray" object itself doesn't implement the "Serializable" interface. Remember that in order to an object be serializable then all of its attributes must implement the "Serializable" interface. Now what can you do? You should implement the "Parcelable" interface of Android, but how? If you have problems using the "SparseArray" in the parcelable process then you can parcel it to another object and the recreate the original "SparseArray" object in the creation process.

Cannot find io/realm/RealmProxy

I have a problem similiar to Realm.io can't get examples to work.
I tried the fix that was written there, but it still doesn't work.
I created two Realmclasses inside my AndroidApp for my Data.
Class one is called "Fahrt":
#RealmClass
public class Fahrt extends RealmObject {
private String fahrtname;
private String fahrtzeitstempel;
private String fahrtfahrzeug;
private RealmList<Data> listData;
public String getFahrtname() {
return fahrtname;
}
public void setFahrtname(String fahrtname) {
this.fahrtname = fahrtname;
}
public String getFahrtzeitstempel() {
return fahrtzeitstempel;
}
public void setFahrtzeitstempel(String fahrtzeitstempel) {
this.fahrtzeitstempel = fahrtzeitstempel;
}
public String getFahrtfahrzeug() {
return fahrtfahrzeug;
}
public void setFahrtfahrzeug(String fahrtfahrzeug) {
this.fahrtfahrzeug = fahrtfahrzeug;
}
public RealmList<Data> getListData() {
return listData;
}
public void setListData(RealmList<Data> listData) {
this.listData = listData;
}
}
Class two is called "Data":
#RealmClass
public class Data extends RealmObject {
private String zeitstempel;
private String header;
private String canid;
private String data;
public String getZeitstempel() {
return zeitstempel;
}
public void setZeitstempel(String zeitstempel) {
this.zeitstempel = zeitstempel;
}
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public String getCanid() {
return canid;
}
public void setCanid(String canid) {
this.canid = canid;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
I tried to store some data in this way.
//global declarations
private static String fahrtname;
private Realm realm;
private Fahrt aktuellefahrt;
private Data addData;
private static StringBuilder sb;
private String datensatz_string;
....
realm = Realm.getInstance(mContext);
//myPersistMethod
private void persist(byte[] message)
{
realm.beginTransaction();
aktuellefahrt = realm.where(Fahrt.class).equalTo("fahrtname", fahrtname).findFirst();
if(aktuellefahrt == null)
{
aktuellefahrt = realm.createObject(Fahrt.class);
aktuellefahrt.setFahrtname(fahrtname);
aktuellefahrt.setFahrtzeitstempel(fahrtname);
aktuellefahrt.setFahrtfahrzeug("testFahrzeug");
}
RealmList<Data> realmListData = aktuellefahrt.getRealmListData();
if(realmListData == null)
{
realmListData = new RealmList<>();
}
datensatz_string = new String(toBinary(message));
addData = realm.createObject(Data.class);
addData.setZeitstempel((datensatz_string.substring(0,16)));
addData.setHeader(datensatz_string.substring(16, 24));
addData.setCanid((datensatz_string.substring(24, 56)));
addData.setData((datensatz_string.substring(56)));
aktuellefahrt.getRealmListData().add(addData);
realm.commitTransaction();
}
...
I allways get the error:
Error:Execution failed for task ':app:transformClassesWithRealmTransformerForDebug'.
cannot find io/realm/DataRealmProxy: io.realm.DataRealmProxy found in io/realm/DataRealmProxy.class
What did I do wrong?

Comparing two objects using Apache reflection fails

I have two objects that are identical in every way (that I am aware of) - in other words, all properties are identical.
Object A
Object B
The class implements Apache reflection is as such:
public class Base<T> {
#Override
public boolean equals(Object obj) {
try {
if (!this.getClass().isInstance(obj)) {
return false;
}
if(EqualsBuilder.reflectionEquals(this, obj)){
return true;
}
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
Where org.apache.commons.lang.builder.EqualsBuilder is the namespace used.
However, whenever I use this equal method to compare them, it returns false.
The objects are implementations of the following:
public class Device extends Base<Object> implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private int _id = -1;
private long create_date = 0;
private long update_date = 0;
private int other_id = -1;
private String description = "";
private int configuration_id = -1;
private long sync_date = 0;
private Device_Info device_info = null;
public int get_id() {
return _id;
}
public void set_id(int _id) {
this._id = _id;
}
public long getCreate_date() {
return create_date;
}
public void setCreate_date(long create_date) {
this.create_date = create_date;
}
public long getUpdate_date() {
return update_date;
}
public void setUpdate_date(long update_date) {
this.update_date = update_date;
}
public int getOther_id() {
return other_id;
}
public void setOther_id(int other_id) {
this.other_id = other_id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getConfiguration_id() {
return configuration_id;
}
public void setConfiguration_id(int configuration_id) {
this.configuration_id = configuration_id;
}
public void setSync_date(long sync_date) {
this.sync_date = sync_date;
}
public long getSync_date() {
return sync_date;
}
/**
*
* #return
*/
public ContentValues getContentValues() {
// define an object to contain the object values
ContentValues values = new ContentValues();
try {
// set the values of each table column.
if(this.get_id() > 0){
values.put("_id", this.get_id());
}
values.put("create_date", this.getCreate_date());
values.put("update_date", this.getUpdate_date());
values.put("description", this.getDescription());
values.put("other_id", this.getOther_id());
values.put("configuration_id", this.getConfiguration_id());
values.put("sync_date", this.getSync_date());
return values;
} catch (Exception e) {
return values;
}
}
public Device_Info getDevice_info() {
return device_info;
}
public void setDevice_info(Device_Info device_info) {
this.device_info = device_info;
}
}
Device info is another class similar to the device class (an extension really), but just has more detailed properties. As previously mentioned, these two objects are identical - I set each property manually to the same value in each object and verify by checking each property individually.
This method works on more simple objects, but I do not understand why it fails on this more complex object? By complex I mean a class that has another class as a property. The Android ContentValues does not appear to affect success/fail.

Categories

Resources