Realm not update existing data in ONE-MANY Relationship Android - 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

Related

How to put ArrayObjectAdapter items in order

I am displaying multiple rows in one header and there is 5 more categories like drama and I am doing the same job for them. My question is when I set the adapter categories displaying randomly.(assuming of request speed).For example I want the display Drama on the first line always. I gave them id of adapter's constructor but didn't work out. Code :
if (response.body().getItems().size() > 0) {
Log.d("Drama",""+response.body().getItems().size());
List<MovieItem> newMovieItems = response.body().getItems();
HeaderItem liveHeader = new HeaderItem("Drama");
LiveChannelPresenter liveChannelPresenter = new LiveChannelPresenter();
ArrayObjectAdapter liveRowAdapter = new ArrayObjectAdapter(liveChannelPresenter);
for (int i = 0; i < newMovieItems.size(); i++) {
movieItem2 = response.body().getItems().get(i);
liveRowAdapter.add(movieItem2);
}
mRowsAdapter.add(new ListRow(0,liveHeader,liveRowAdapter));
}
}
if (response.body().getItems().size() > 0) {
Log.d("Drama",""+response.body().getItems().size());
List<MovieItem> newMovieItems = response.body().getItems();
//sorted:
Arrays.sort(newMoviewItems, new Comparator() { some condition to sort });
HeaderItem liveHeader = new HeaderItem("Drama");
LiveChannelPresenter liveChannelPresenter = new LiveChannelPresenter();
ArrayObjectAdapter liveRowAdapter = new ArrayObjectAdapter(liveChannelPresenter);
for (int i = 0; i < newMovieItems.size(); i++) {
//note the change here \|/
movieItem2 = newMoviewItems.get(i);
liveRowAdapter.add(movieItem2);
}
mRowsAdapter.add(new ListRow(0,liveHeader,liveRowAdapter));
}

Difference between BarEntry and RadarEntry when added to a DataSet asynchronously

I am working on two different charts, one is a RadarChart that compares the scores of all "categories" in an "assessment" to other "assessments", and a grouped BarChart that allows the user to select "categories" in an "assessment" and compare them to other "assessments". The data is pulled from Firebase and the DatabaseReferences are stored in an ArrayList. My RadarChart uses the following code and displays the following result:
ArrayList<RadarDataSet> dataSets = new ArrayList<>();
ArrayList<IRadarDataSet> allDataSets = new ArrayList<>();
for(int i = 0; i < assessmentKeys.size(); i++) {
final ArrayList<RadarEntry> radarEntries = new ArrayList<>();
final int trackerIndex = i;
dataSets.add(trackerIndex, new RadarDataSet(radarEntries, assessmentName.get(i)) );
mAssessmentCategoryRefs.get(i).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
for(DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
Category category = postSnapshot.getValue(Category.class);
radarEntries.add(new RadarEntry((float)category.getCategoryScore(), category.getNumber() - 1));
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Random random = new Random();
int randomR = random.nextInt(256);
int randomG = random.nextInt(256);
int randomB = random.nextInt(256);
dataSets.get(trackerIndex).setColor(Color.rgb(randomR, randomG, randomB));
dataSets.get(trackerIndex).setFillColor(Color.rgb(randomR, randomG, randomB));
dataSets.get(trackerIndex).setDrawFilled(true);
allDataSets.add(dataSets.get(trackerIndex));
}
RadarData data = new RadarData(allDataSets);
Because RadarEntry, BarEntry, BarDataSet, RadarDataSet, IBarDataSet, and IRadarDataSet all share parent classes between them, I assumed that I would be able to load data into a grouped BarChart in the same manner that I did with the RadarChart. For a proof of concept, I used the following code to verify that it will work before attempting to pull from Firebase:
final ArrayList<BarDataSet> dataSets = new ArrayList<>();
ArrayList<IBarDataSet> allDataSets = new ArrayList<>();
for(int j = 0; j < assessmentKeys.size(); j++ ) {
final int jTracker = j;
final ArrayList<BarEntry> entries = new ArrayList<>();
dataSets.add(j, new BarDataSet(entries, assessmentName.get(j)));
Log.d("Received_Data", "Getting data for " + assessmentName.get(j));
for(int k = 0; k < categoryNames.size(); k++) {
entries.add(new BarEntry(k, k+1));
}
Random random = new Random();
int randomR = random.nextInt(256);
int randomG = random.nextInt(256);
int randomB = random.nextInt(256);
dataSets.get(j).setColor(Color.rgb(randomR, randomG, randomB));
allDataSets.add(dataSets.get(j));
}
This produced this chart:
When I add code to pull from firebase, something weird happens that does not happen with the RadarChart:
final ArrayList<BarDataSet> dataSets = new ArrayList<>();
ArrayList<IBarDataSet> allDataSets = new ArrayList<>();
for(int j = 0; j < assessmentKeys.size(); j++ ) {
final int jTracker = j;
final ArrayList<BarEntry> entries = new ArrayList<>();
dataSets.add(j, new BarDataSet(entries, assessmentName.get(j)));
Log.d("Received_Data", "Getting data for " + assessmentName.get(j));
for(int k = 0; k < categoryNames.size(); k++) {
final String categoryName = categoryNames.get(k);
final int kTracker = k;
mAssessmentCategoryRefs.get(jTracker).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
for(DataSnapshot postSnapShot : dataSnapshot.getChildren()) {
Category category = postSnapShot.getValue(Category.class);
if(categoryName.equals(category.getName())) {
entries.add(new BarEntry(kTracker, (float)category.getCategoryScore()));
Log.d(TAG, "Added " + category.getName() + " to entries");
} else {
Log.d(TAG, "Skipped " + category.getName());
}
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Random random = new Random();
int randomR = random.nextInt(256);
int randomG = random.nextInt(256);
int randomB = random.nextInt(256);
dataSets.get(j).setColor(Color.rgb(randomR, randomG, randomB));
allDataSets.add(dataSets.get(j));
}
BarData data = new BarData(allDataSets);
mBarChart.setData(data);
data.notifyDataChanged();
mBarChart.notifyDataSetChanged();
mBarChart.invalidate();
The data is not charted, even though my logs show that it correctly skips categories that dont match a selected name and adds the category's score if it does.
What is the cause of this? At first I thought that it may be due to the async nature of the data being pulled from firebase, but if that were the case, my RadarChart would experience the same issue. As far as I can tell the only real difference between RadarEntry and BarEntry is that the index is the second argument in a RadarEntry but the first in a BarEntry.The entries are loaded into the DataSet in the same manner, the DataSets are loaded into the ArrayList<IBarDataSet> in the same manner, yet for some reason one works and the other does not. Does anyone know what the issue is? Is this a bug with MPAndroidChart's explicit BarEntry?
I found a work around. First, I had to create an initialization method that is called in onCreate():
private Map<String, Map<String, Float>> assessmentData = new HashMap<>();
private void initAssessmentData() {
for(int i = 0; i < assessmentKeys.size(); i++) {
final Map<String, Float> categoryNameScore = new HashMap<>();
mAssessmentCategoryRefs.get(i).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
for(DataSnapshot postSnapShot : dataSnapshot.getChildren()) {
Category category = postSnapShot.getValue(Category.class);
categoryNameScore.put(category.getName(), (float) category.getCategoryScore());
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
assessmentData.put(assessmentKeys.get(i), categoryNameScore);
}
}
Then to put the data into the graph I just had to change my code to this:
final ArrayList<BarDataSet> dataSets = new ArrayList<>();
ArrayList<IBarDataSet> allDataSets = new ArrayList<>();
final BarData data = new BarData(allDataSets);
for(int j = 0; j < assessmentKeys.size(); j++ ) {
final int jTracker = j;
final ArrayList<BarEntry> entries = new ArrayList<>();
dataSets.add(j, new BarDataSet(entries, assessmentName.get(j)));
Log.d("Received_Data", "Getting data for " + assessmentName.get(j));
for(String key : assessmentData.keySet()) {
if(key.equals(assessmentKeys.get(j))) {
Map<String, Float> categoryData = assessmentData.get(key);
for(String key2 : categoryData.keySet()) {
if(categoryNames.contains(key2)) {
entries.add(new BarEntry(categoryNames.indexOf(key2), categoryData.get(key2)));
}
}
}
}
Random random = new Random();
int randomR = random.nextInt(256);
int randomG = random.nextInt(256);
int randomB = random.nextInt(256);
dataSets.get(j).setColor(Color.rgb(randomR, randomG, randomB));
allDataSets.add(dataSets.get(j));
data.notifyDataChanged();
mBarChart.notifyDataSetChanged();
mBarChart.invalidate();

Why does WorkManager doesn't work correctly with OneTimeWorkRequest?

I have problem with WorkManager from Android Architecture Components.
version of workmanager is alpha-06
Maybe I didn't understand this process, but I expect that OneTimeWorkRequest will work only once, and it work correctly if time for this work not very long (not more than 7+- minutes), but if more, workmanager start the same work again (with same UUID) and not stop first work, and workmanager execute two works in parallel
Here I start work
Data workDownloadBookData = new Data.Builder().putInt(BookDownloadWork.BOOK_ID_KEY, id).putString(BookDownloadWork.COUNTRY_CODE_KEY, countryCode).build();
OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(BookDownloadWork.class)
.setInputData(workDownloadBookData)
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 2L, TimeUnit.SECONDS)
.build();
WorkManager workManager = WorkManager.getInstance();
if (workManager != null) {
workManager.beginUniqueWork(countryCode + id,ExistingWorkPolicy.KEEP, request).enqueue();
}
It is my work
public class BookDownloadWork extends Worker {
private static final String TAG = BookDownloadWork.class.getSimpleName();
public static final String COUNTRY_CODE_KEY = "COUNTRY_CODE_KEY";
public static final String LAST_UPDATE_KEY = "LAST_UPDATE_KEY";
public static final String BOOK_ID_KEY = "BOOK_ID_KEY";
public static final String PHOTO_URI_KEY = "PHOTO_URI_KEY";
private BookRepository bookRepository;
private BookLoadProgressDao bookLoadProgressDao;
private BookLoadWorkerDao bookLoadWorkerDao;
private NotificationController notificationController;
#NonNull
#Override
public Result doWork() {
bookRepository = App.appComponent.getBookRepository();
bookLoadProgressDao = App.appComponent.getBookLoadProgressDao();
bookLoadWorkerDao = App.appComponent.getBookLoadWorkerDao();
notificationController = App.appComponent.getNotificationController();
String countryCode = getInputData().getString(COUNTRY_CODE_KEY);
// String countryCode = getInputData().getString(COUNTRY_CODE_KEY, "");
int serverBookId = getInputData().getInt(BOOK_ID_KEY, 0);
if (!TextUtils.isEmpty(countryCode) && serverBookId != 0) {
String localBookId = serverBookId + countryCode;
BookLoadProgress bookLoadProgress = new BookLoadProgress();
bookLoadProgress.setId(localBookId);
try {
LocalBookDetail localBookDetail = bookRepository.selectLocalBookDetailSynch(serverBookId, countryCode);
bookRepository.saveBookToLocalStorageSynch(serverBookId, localBookDetail.getLastUpdate(), countryCode, null);
BookLoadWorker bookLoadWorker = new BookLoadWorker();
bookLoadWorker.setBookId(localBookId);
bookLoadWorker.setWorkId(getId());
bookLoadWorkerDao.insertBookLoadWorker(bookLoadWorker);
RemoteBookChapter[] remoteBookChapters = bookRepository.loadBookFromServerSynch(countryCode, serverBookId);
if (remoteBookChapters == null) return Result.FAILURE;
//count max progress
for (int i = 0; i < remoteBookChapters.length; i++) {
RemoteBookChapter remoteBookChapter = remoteBookChapters[i];
if (remoteBookChapter.getType().equals("image")) { bookLoadProgress.setMaxProgress(bookLoadProgress.getMaxProgress() + 1);
for (int j = 0; j < remoteBookChapter.getContent().length; j++) {
RemoteBookContent remoteBookContent = remoteBookChapter.getContent()[j];
if (remoteBookContent.getType().equals("image")) {
bookLoadProgress.setMaxProgress(bookLoadProgress.getMaxProgress() + 1);
}
}
}
}
bookLoadProgressDao.insertBookLoadProgress(bookLoadProgress);
for (int i = 0; i < remoteBookChapters.length; i++) {
RemoteBookChapter remoteBookChapter = remoteBookChapters[i];
if (remoteBookChapter.getType().equals("image")) { remoteBookChapter.setUrl(bookRepository.loadAndSaveImageSynch(remoteBookChapter.getUrl())); bookLoadProgress.setCurrentProgress(bookLoadProgress.getCurrentProgress() + 1);
bookLoadProgressDao.insertBookLoadProgress(bookLoadProgress);
for (int j = 0; j < remoteBookChapter.getContent().length; j++) {
RemoteBookContent remoteBookContent = remoteBookChapter.getContent()[j];
if (remoteBookContent.getType().equals("image")) {
remoteBookContent.setUrl(bookRepository.loadAndSaveImageSynch(remoteBookContent.getUrl())); bookLoadProgress.setCurrentProgress(bookLoadProgress.getCurrentProgress() + 1); bookLoadProgressDao.insertBookLoadProgress(bookLoadProgress);
}
}
}
}
bookRepository.saveBookToLocalStorageSynch(serverBookId, localBookDetail.getLastUpdate(), countryCode, remoteBookChapters);
bookLoadProgressDao.deleteBookLoadProgress(bookLoadProgress.getId());
notificationController.sendNotificationAboutBookDownloadFinished(serverBookId, countryCode);
return Result.SUCCESS;
} catch (Exception e) {
Log.e(TAG, "doWork: ",e );
// bookLoadProgressDao.deleteBookLoadProgress(bookLoadProgress.getId());
bookRepository.deleteBookSycnh(localBookId);
return Result.FAILURE;
}
} else {
return Result.FAILURE;
}
}
}
but I need only one work for download these files and save it to database
I think you are mixing a few concepts. OneTimeWorkRequest's are not unique by themselves. If you only want one instance of the continuation run, then you should be using unique work. Look athe documentation for beginUniqueWork.

How to add data in array on button click?

int size = mcq.size();
String arr[] = null;
int i;
{
for (i = 0; i < size; i++) {
if (op1.isPressed()) {
arr[i] = tv1.getText().toString();
// Log.e("Array",arr[i]);
} else if (op2.isPressed()) {
arr[i] = tv2.getText().toString();
//Log.e("Array",arr[i]);
} else if (op3.isPressed()) {
arr[i] = tv3.getText().toString();
// Log.e("Array",arr[i]);
} else if (op4.isPressed()) {
arr[i] = tv4.getText().toString();
//Log.e("Array",arr[i]);
}
I am trying to store the data in an array when the button is pressed,but it always shows null.And when the for loop is over I want to display my array.
here , Arrays in Java have a size so u cannot do like this. Instead of this
use list,
ArrayList<String> arr = new ArrayList<String>();
Inorder to do using String array :
String[] arr = new String[SIZEDEFNE HERE];
For ur answer :
ArrayList<String> arr = new ArrayList<String>();
int i;
{
for (i = 0; i < size; i++) {
if (op1.isPressed()) {
arr.add(tv1.getText().toString());
} else if (op2.isPressed()) {
arr.add(tv2.getText().toString());
} else if (op3.isPressed()) {
arr.add(tv3.getText().toString());
} else if (op4.isPressed()) {
arr.add(tv4.getText().toString());
}
Retrive value using
String s = arr.get(0);
This is because your string array is null. Declare it with the size as
String[] arr = new String[size];
Try Array List. use the following code in your main java
final ArrayList<String> list = new ArrayList<String>();
Button button= (Button) findViewById(R.id.buttonId);
final EditText editText = (EditText) findViewById(R.id.editTextId)
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
list.add(editText.getText().toString());
}
});
To avoid duplication in arraylist .You can use arraylist for faster then String array
ArrayList<String> list = new ArrayList<String>();
list.add("Krishna");
list.add("Krishna");
list.add("Kishan");
list.add("Krishn");
list.add("Aryan");
list.add("Harm");
System.out.println("List"+list);
HashSet hs = new HashSet();
hs.addAll(list);
list.clear();
list.addAll(hs);

How to sort numbers in TextViews and display them?

Hi can some one suggest me a sample example of how i can sort the textviews based on the numbers in textviews. I am able to get the text from the TextViews need to sort and place the lowest number first.
Thank you.
public void sortNumbers(View v) {
String[] numbers = new String[7];
numbers[0] = textView23.getText().toString();
numbers[1] = textView33.getText().toString();
numbers[2] = textView43.getText().toString();
numbers[3] = textView53.getText().toString();
numbers[4] = textView63.getText().toString();
numbers[5] = textView73.getText().toString();
numbers[6] = textView83.getText().toString();
Integer[] intValues = new Integer[numbers.length];
for (int i = 0; i < numbers.length; i++) {
intValues[i] = Integer.parseInt(numbers[i].trim());
}
Collections.sort(Arrays.asList(intValues));
for (int i = 0; i < intValues.length; i++) {
Integer intValue = intValues[i];
//here I want to assign sorted numberes to the TextViews
}
}
So I have followed Jeffrey's advice. Here is the code which still doesn't work properly. What could be wrong?
Created an array of TextViews:
TextView[] tvs = new TextView[7];
tvs[0] = textView23;
tvs[1] = textView33;
tvs[2] = textView43;
tvs[3] = textView53;
tvs[4] = textView63;
tvs[5] = textView73;
tvs[6] = textView83;
Sorted the array and assinged new values to the TextViews:
Arrays.sort(tvs, new TVTextComparator());
textView23.setText(tvs[0].getText().toString());
textView33.setText(tvs[1].getText().toString());
textView43.setText(tvs[2].getText().toString());
textView53.setText(tvs[3].getText().toString());
textView63.setText(tvs[4].getText().toString());
textView73.setText(tvs[5].getText().toString());
textView83.setText(tvs[6].getText().toString());
And here is the Comporator class:
public class TVTextComparator implements Comparator<TextView> {
public int compare(TextView lhs, TextView rhs) {
Integer oneInt = Integer.parseInt(lhs.getText().toString());
Integer twoInt = Integer.parseInt(rhs.getText().toString());
return oneInt.compareTo(twoInt);
}
}
to sort your textViews, first put them in an array,
TextView[] tvs = new TextView[7];
tvs[0] = textView23;
tvs[1] = textView33;
// and so on
note that if you have handle to the parent container, you could easily build the array by using ViewGroup.getChildCount() and getChildAt().
now write a comparator for a text view,
class TVTextComparator implements Comparator<TextView> {
#Override
public int compare(TextView lhs, TextView rhs) {
return lhs.getText().toString().compareTo(rhs.getText().toString());
// should check for nulls here, this is NOT a robust impl of compare()
}
}
now use the comparator to sort the array,
Arrays.sort(tvs, 0, tvs.length, new TVTextComparator());
public void sortNumbers(View v) {
String[] numbers = new String[7];
numbers[0] = textView23.getText().toString();
numbers[1] = textView33.getText().toString();
numbers[2] = textView43.getText().toString();
numbers[3] = textView53.getText().toString();
numbers[4] = textView63.getText().toString();
numbers[5] = textView73.getText().toString();
numbers[6] = textView83.getText().toString();
Integer[] intValues = new Integer[numbers.length];
for (int i = 0; i < numbers.length; i++) {
intValues[i] = Integer.parseInt(numbers[i].trim());
}
Collections.sort(Arrays.asList(intValues));
textView23.setText(intValues[0]);
textView33.setText(intValues[1]);
textView43.setText(intValues[2]);
textView53.setText(intValues[3]);
textView63.setText(intValues[4]);
textView73.setText(intValues[5]);
textView83.setText(intValues[6]);
}

Categories

Resources