copyToRealm copies an empty list instead of a populated one - android

I have a RealmObject called "Encounter", which contains a RealmList of other RealmObjects called "SavedCombatant". In my code, I populate the RealmList with the appropriate objects, but when I commit the transaction and retrieve the Encounter-Object later, the RealmList is empty.
I have the following code
public void saveEncounter(){
//create a new key for the encounter
int key = 0;
if(mRealm.where(Encounter.class).count() != 0) {
RealmResults<Encounter> encounters = mRealm.where(Encounter.class).findAll();
Encounter encounter = encounters.last();
key = encounter != null ? encounter.getKey() + 1 : 0;
}
// retrieve the data to populate the realmlist with
// combatants has 1 element
List<SavedCombatant> combatants = mAdapter.getCombatants();
mRealm.beginTransaction();
Encounter e = mRealm.createObject(Encounter.class);
e.setKey(key);
e.setTitle(txtTitle.getText().toString());
RealmList<SavedCombatant> combatantRealmList = new RealmList<>();
for (int i = 0; i < combatants.size(); i++) {
combatantRealmList.add(combatants.get(i));
}
//combatantRealmList also has 1 element. setCombatants is a
//generated Setter with a couple bits of additional logic in it
e.setCombatants(combatantRealmList);
mRealm.copyToRealm(e);
mRealm.commitTransaction();
}
this would be my Encounter class
public class Encounter extends RealmObject {
private int key;
private String title;
private RealmList<SavedCombatant> combatants;
#Ignore
private String contents;
public void setCombatants(RealmList<SavedCombatant> combatants) {
//simple setter
this.combatants = combatants;
//generate summary of the elements in my realmlist. (probably inefficient as hell, but that's not part of the problem)
HashMap<String, Integer> countMap = new HashMap<>();
for (int i = 0; i < combatants.size(); ++i) {
String name = combatants.get(i).getName();
int countUp = 1;
if (countMap.containsKey(name)) {
countUp = countMap.get(name) + 1;
countMap.remove(name);
}
countMap.put(name, countUp);
}
contents = "";
Object[] keys = countMap.keySet().toArray();
for (int i = 0; i < keys.length; ++i) {
contents += countMap.get(keys[i]) + "x " + keys[i];
if (i + 1 < keys.length)
contents += "\r\n";
}
}
// here be more code, just a bunch of getters/setters
}
the class used for the RealmList has the following header (as to verify that I'm using a RealmObject here aswell)
public class SavedCombatant extends RealmObject

As it turns out, you need to explicitly save Objects inside a RealmList.
I needed to copy my SavedCombatant object to realm inside my for loop, using
mRealm.copyToRealm(combatants.get(i));

Related

Realm not update existing data in ONE-MANY Relationship Android

I have been using realm about more than a years, in many cases realm is good choice to construct Android database instead using SQLite. I have been using realm for one-one, one-many relationship and good for it. But, a moment a good. I discover realm NOT update my existing data in ONE-MANY relationship. This what i have done.
This code for populate skeleton data or a unit test
private void initData() {
List<PackModel> packs = new ArrayList<>();
for (int i = 0; i < 1; i++) {
PackModel packModel = new PackModel();
packModel.id = i;
packModel.name = "Pack " + new Random().nextInt(100);
List<FoodModel> foods = new ArrayList<>();
for (int j = 0; j < 3; j++) {
FoodModel foodModel = new FoodModel();
foodModel.id = 0; // i set primary key 0, so in list should be 3 but when insert should be JUST one
foodModel.packId = i;
foodModel.name = "Food " + new Random().nextInt(100);
foodModel.stock = new Random().nextInt(100);
foodModel.price = new Random().nextInt(100);
foodModel.image = "hrrp";
foodModel.calorie = new Random().nextInt(100);
foodModel.createTime = System.nanoTime();
foods.add(foodModel);
}
packModel.foods.addAll(foods);
packs.add(packModel);
}
insertdb(packs);
}
As you see a List of PackModel, and each PackModel have their food items.
So, i write in Realm like below code.
private void insertdb(final List<PackModel> items) {
new AsyncTask<Void, Void, List<PackObject>>() {
#Override
protected List<PackObject> doInBackground(Void... params) {
final List<PackObject> packsObject = new ArrayList<>();
for (int i = 0; i < items.size(); i++) {
PackObject packObject = new PackObject();
packObject.id = items.get(i).id;
packObject.name = items.get(i).name;
List<FoodObject> foodsObject = new ArrayList<>();
for (int j = 0; j < items.get(i).foods.size(); j++) {
FoodObject foodObject = new FoodObject();
foodObject.id = items.get(i).foods.get(j).id;
foodObject.name = items.get(i).foods.get(j).name;
foodObject.createdTime = items.get(i).foods.get(j).createTime;
foodsObject.add(foodObject);
}
packObject.foods.addAll(foodsObject);
packsObject.add(packObject);
}
Realm realm = Realm.getInstance(RealmApplication.getRealmConfiguration());
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(packsObject);
}
});
return realm.copyFromRealm(realm.where(PackObject.class).findAll());
}
#Override
protected void onPostExecute(List<PackObject> items) {
super.onPostExecute(items);
Log.d("Test", "");
}
}.execute();
}
I got multiple FoodObject in each PackObject, what i am wrong here? i also use realm.beginTransaction. realm.beginTransaction is just a same like execute*, the difference just execute* are thread safe.
i also use realm.insertOrUpdate(obj), but just have same result.
NOTE: I have read realm documentation about it. So dont judge me not read their documentation.
this my repot for the code https://github.com/radityagumay/realm-bug
Thanks

Assign Integer Value to String

I am developing an app in which i have to assign integer values to different string of words. For Example I want to assign:
John = 2
Good = 3
Person= 7
Now these John, Good and person are strings while 2,3 and 7 are int values. But I am so confused about how to implement that. I read many things about how to convert int to string and string to int but this is different case.
I am giving option to user to enter a text in editText and if for example User enters "Hello John you are a good person" then this line output will be 12 as all the three words John, Good and person are there in the input text. Can you tell me how to achieve that?
I am stuck here is my little code:
String s = "John";
int s_value= 2;
now I want to assign this 2 to John so that whenever user give input and it contains John then the value 2 is shown for John. Please Help as I am just a beginner level programmer
Here is my code (Edited)
String input = "John good person Man";
Map<String, Integer> map = new HashMap<>();
map.put("John", 2);
map.put("Good", 3);
map.put("Person", 7);
//int number = map.get("Good");
String[] words = input.split(" ");
ArrayList<String> wordsList = new ArrayList<String>();
for(String word : words)
{
wordsList.add(word);
}
for (int ii = 0; ii < wordsList.size(); ii++) {
// get the item as string
for (int j = 0; j < stopwords.length; j++) {
if (wordsList.contains(stopwords[j])) {
wordsList.remove(stopwords[j]);//remove it
}
}
}
for (String str : wordsList) {
Log.e("msg", str + " ");
}
As u see i applied code of you and then i want to split my main string so that each word of that string compares with the strings that are in the Map<>. Now i am confused what to write in the for loop ( 'stopwords' will be replaced by what thing?)
You can use a Map<String, Integer> to map words to numbers:
Map<String, Integer> map = new HashMap<>();
map.put("John", 2);
map.put("Good", 3);
map.put("Person", 7);
and then query the number given a word:
int number = map.get("John"); // will return 2
UPDATE
The following code iterates over a collection of words and adds up the values that the words match to:
List<String> words = getWords();
int total = 0;
for (String word : words) {
Integer value = map.get(word);
if (value != null) {
total += value;
}
}
return total;
I would use a Dictionary for this. You can add a string and an int (or anything else actually) value for that string.
Dictionary<string, int> d = new Dictionary<string, int>();
d.Add("John", 2);
d.Add("Good", 3);
d.Add("Person", 7);
You can use String contains to achieve this. Following is the code:
String input = "John you are a good person";
String s1 = "John";
String s2 = "good";
String s3 = "person";
int totScore =0;
if(input.contains(s1)) {
totScore=totScore+2;
}
else if (input.contains(s2)) {
totScore=totScore+3;
}
else if (input.contains(s3)) {
totScore=totScore+7;
}
System.out.print(totScore);
You can use class like.
class Word{
String wordName;
int value;
public Word(String wordName, int value){
this.wordName = wordName;
this.value = value;
}
// getter
public String getWordName(){
return this.wordName;
}
public int getValue(){
return this.value;
}
// setter
public void setWordName(String wordName){
this.wordName = wordName;
}
public void zetValue(int value){
this.value = value;
}
}
You can create an object of the word
Word person = new Word("Person",3);

Sort two dependent string arrays

I Have two String arrays in my application, One containing Country names, and other containing corresponding extension code, But the issue is that the names of countries are not properly ordered in alphabetical order,
public static final String[] m_Countries = {
"---select---", "Andorra", ...., "Zimbabwe"};
public static final String[] m_Codes = {
"0", "376",...., "263"};
These are the arrays,
So my question is, is there any way to sort the first array such that the second array also changes to corresponding position without writing my own code?
If not, what's the best sort method i can use for these arrays?
Any kind of help will be greatly appreciated.
Form TreeMap from your array and all your data get sort. After that fill your respective array with Key and Values.
TreeMap<String, String> map = new TreeMap<>();
int length = m_Countries.length;
for(int i=0;i<length;i++){
map.put(m_Countries[i], m_Codes[i]);
}
String[] countries = map.keySet().toArray(new String[map.keySet().size()]);
System.out.println("Country:"+Arrays.toString(countries));
String[] codes = map.values().toArray(new String[map.values().size()]);
System.out.println("Codes:"+Arrays.toString(codes));
Result:
Country:[---select---, Afghanistan, ..., Zimbabwe]
Codes:[0, 93,.... , 263]
Method 1.
You can create a hashMap to store the original country to code.
private void handle(String[] m_Countries, String[] m_Codes, Map<String, String> map) {
if (m_Codes == null || m_Countries == null || map == null) {
return;
}
//
final int codeCount = m_Codes.length;
final int countryCount = m_Countries.length;
final int count = Math.min(codeCount, countryCount);
for (int i = 0; i < count; i++) {
map.put(m_Countries[i], m_Codes[i]);
}
// TODO sort
// get code by country name by map.get(country)
}
Method 2.
You can make a List of pairs which contains country and code. Then sort the list.
private List<Pair<String, String>> sortCountryWithCode(String[] m_Countries, String[] m_Codes) {
if (m_Codes == null || m_Countries == null) {
return null;
}
//
final int codeCount = m_Codes.length;
final int countryCount = m_Countries.length;
final int count = Math.min(codeCount, countryCount);
if (count == 0) {
return null;
}
// generate a list
List<Pair<String, String>> list = new ArrayList<>();
for (int i = 0; i < count; i++) {
list.add(new Pair<String, String>(m_Countries[i], m_Codes[i]));
}
// sort
Collections.sort(list, new Comparator<Pair<String, String>>() {
#Override
public int compare(Pair<String, String> lhs, Pair<String, String> rhs) {
return lhs.first.compareToIgnoreCase(rhs.first);
}
});
return list;
}
code with love. :)

Adding Array in SQLite While Loop

I am using this -> http://www.ezzylearning.com/tutorial.aspx?tid=1763429 to create my own custom listview.
For my project, I am using while loop to get data and getting data back.
The original code is :
DownloadClass data[] = new DownloadClass[] {
new DownloadClass("test", "test"),
new DownloadClass("test", "Sunny")
};
However for my case..
DownloadClass data[] = new DownloadClass[] {};
SQLFunctions entry = new SQLFunctions(this);
entry.open();
highestID = entry.getHighestId();
for (int l = 1; l < highestID; l++) {
Long longVal = Long.valueOf(l);
new DownloadClass(entry.getName(longVal).toString(), entry.getURL(longVal).toString());
}
The listview appears to be empty because I know the data is not inserted. Any help is appreciated. Thanks.
EDIT :
my DownloadClass :
public class DownloadClass {
public String name;
public String url;
public DownloadClass(){
super();
}
public DownloadClass(String name, String url) {
super();
this.name = name;
this.url = url;
}
}
My new Activity
DownloadClass data[] = new DownloadClass[]; // need to work on this
SQLFunctions entry = new SQLFunctions(this);
entry.open();
highestID = entry.getHighestId();
Log.e("HIGHEST ID", highestID.toString());
if (highestID > 1) {
for (int l = 0; l < highestID; l++) {
Long longVal = Long.valueOf(l);
//String name = entry.getName(longVal);
//String id = entry.getURL(longVal);
//Log.e("NAME", name + " - " + id);
data[l] = new DownloadClass(entry.getName(longVal).toString(),entry.getURL(longVal).toString());
}
}
entry.close();
You're not ever adding your new DownloadClass object to your array. You also need to allocate size if you're going to use an array instead of an ArrayList (which to be honest is probably what you want).
As you iterate through the loop you need to assign the new object to a position in the array.
data[i] = new DownloadClass(...);
Try this and let me know what happen..
DownloadClass data[];
SQLFunctions entry = new SQLFunctions(this);
entry.open();
highestID = entry.getHighestId();
data[] = new DownloadClass[highestID];
for (int l = 0; l < highestID; l++) {
Long longVal = Long.valueOf(l);
data[i] = new DownloadClass(entry.getName(longVal).toString(), entry.getURL(longVal).toString());
}
Also start your loop with 0 index.. instead of 1..
Update:
First of all you are dynamically creating array of object. SO you have to know the size of array.
Second your loop is start with index 1, it should be 0.

Trying to set textview

Here is my class it goes in to infinite loop please check where I am going wrong ... I am trying to get id's of image view making it random and then trying to set text view with imageview's description
public class Object {
int ObectIds[];
LinearLayout HUDDisplay;
int HudDisplayText[] = {R.id.HUD_Text_Element1,
R.id.HUD_Text_Element2,
R.id.HUD_Text_Element3,
R.id.HUD_Text_Element4,
R.id.HUD_Text_Element5,
R.id.HUD_Text_Element6,
R.id.HUD_Text_Element7};
TextView[] text;
View v;
Object(Context context,View vs) {
super();
ObectIds = new int[8];
HUDDisplay=(LinearLayout)vs.findViewById(R.id.HUD_Display);
for (int i = 0; i < 8; i++) {
ObectIds[i] = (R.id.imageView1) + i;
Log.d("ImageView", "Image Id's " + ObectIds[i]);
}
randomize(vs);
setTextView();
}
public void setTextView()
{
for(int i=0;i<8;++i)
{
text[i] =(TextView) HUDDisplay.findViewById(HudDisplayText[i]);
text[i].setText(v.getContentDescription());
}
}
public void randomize(View vs) {
for (int i = 0; i < 8; i++) {
while (true) {
shuffleArray(ObectIds);
v = vs.findViewById(ObectIds[i]);
Log.d("Image", "Image Id's " + v.getId());
if (!v.isClickable()) {
v.setClickable(true);
break;
}
}
}
}
static void shuffleArray(int[] ar) {
Random rnd = new Random();
for (int i = ar.length - 1; i >= 0; i--) {
int index = rnd.nextInt(i + 1);
// Simple swap
int a = ar[index];
ar[index] = ar[i];
ar[i] = a;
}
}
}
Hey man I observed your code & found error in code :
Please compare following code with your code... Constructor
for (int i = 0; i < 8; i++) {
ObectIds[i] = **HudDisplayText[i]**;
Log.d("ImageView", "Image Id's " + ObectIds[i]);
}
You have a while(true) loop that you break from only if v is not clickable. What happens if v is clickable? Nothing in your code ever sets v to not clickable, and views by default are not clickable.
I notice you're using the Object class. Object is basically the root of which all classes extend. If you call super() in the constructor, it will call the super class constructor, which is Object as well... That might be the problem.
Try looking for tutorials on how to start with Java/Android, since you are also using variables names that are not recommended. E.g. in Java,:
- a Class starts with a Capital
- a variable, starts with lowercase
- a function starts with lowercase:
public class Captial
{
private int anIntegerStartsWithLowerCase;
private void functionsAreLowerCaseAsWell()
{
}
}
Also take a look at your loop... It looks like it is never ending

Categories

Resources