How to manage viewmodel - android

I have an activity that has a view model. When I call 2 methods of that view model first execute second method. Why?
How can I manage that methods?
This is onCreate of the activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_news_letter);
dbViewModel = new ViewModelProvider(this).get(DBViewModel.class);
dbViewModel.getLastUpdate().observe(this, s -> {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
try {
Date date = format.parse(s);
timeStamp = (int)date.getTime() / 1000;
getAllNews(BaseCodeClass.CompanyID, timeStamp);
} catch (ParseException e) {
e.printStackTrace();
}
});
dbViewModel.getAllNews().observe(this, newsLetters ->
{
Toast.makeText(this, "3", Toast.LENGTH_SHORT).show();
});
}
In this method first dbViewModel.getAllNews() is executed then dbViewModel.getLastUpdate()

When you observe a LiveData, it will call the onChanged method on its observers when the data is ready or when the data changes. When you observe two or more LiveDatas in a certain order, it doesn't mean that the observers will be called in that order as well. It will happen sometime when the data is ready. That's exactly the behavior of observable fields like LiveData.
If you want to read those values in that exact order and only once, you can call getValue() and get the value right away instead of observing them:
String s = dbViewModel.getLastUpdate().getValue();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
try {
Date date = format.parse(s);
timeStamp = (int)date.getTime() / 1000;
getAllNews(BaseCodeClass.CompanyID, timeStamp);
} catch (ParseException e) {
e.printStackTrace();
}
var newsLetters = dbViewModel.getAllNews().getValue();
Toast.makeText(this, "3", Toast.LENGTH_SHORT).show();
Those values will be read in that order, but they won't be called again if the LiveData values change.

Related

Looping around while using RxJava with Room

I had been trying to use RxJava with Room. The logic is simple, if there is no row for current date, I will create an instance and insert the row into the databse. The problem is that the row is being inserted but its acting like a loop. When I debug, the code goes to run insertTestType, it completes and then comes to the subscriber part of getTestModel and then the counter is 1 and then stops.
private void getTestModel() {
String date = new SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()).format(new Date());
mCompositeDisposable.add(questionDatabase.questionDao().getTestByDate(date, testType)
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(testModels -> {
if (testModels.size() > 0) {
testModel = testModels.get(0);
} else {
testModel = new TestModel(testType, date);
insertTestType();
}
}, throwable -> Log.e("ErrorRx", "exception getModels")));
}
private void insertTestType() {
Completable.fromAction(() -> questionDatabase.questionDao().insert(testModel))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new DisposableCompletableObserver() {
#Override
public void onComplete() {
Log.d(TAG, "onComplete");
}
#Override
public void onError(Throwable e) {
Log.d(TAG, "onError");
}
});
}
The database is,
#Insert
void insert(TestModel testModel);
#Query("SELECT * FROM " + TestModel.TABLE_NAME+ " WHERE " + TestModel.DATE + " = :date" + " AND testType " + "=:testType")
Flowable<List<TestModel>> getTestByDate(String date, TestType testType);
why its coming back to previous subscriber? Thanks in advance.
The code is running just as it should be :)
When you use Flowable, every time the data is updated the Flowable object will emit automatically, notifying all it's subscribers and that's why it invokes code from subscribe in your first method.
If you don't want such behaviour consider using Maybe - more informations here

Constantly retrieve data from database in a infinite loop

I created a database with a table named flagTable, this table only has two fields, which are id(auto increment) and an integer field. Next, in my program, I have a button that will trigger a thread to start. When the thread is starting, it constantly retrieve data from database, and check for the for the value, if the value is equal to one then it will trigger another new Thread, something like this:
private class statusOfStrummingInAnotherDevice extends Thread {
int value;
public void run() {
try{
while(true){
try{
if(flagCursor == null){
flagCursor = cdb1.getFlagAll();
}
}catch(Exception e){break;}
try{
Log.i("MAIN3ACTIVITY","getting status");
int size = cdb1.getSize(flagCursor);
Log.i("MAIN3ACTIVITY","SIZE is" + String.valueOf(xyz));
for(int i = 0 ; i < size ; i++){
flagCursor.moveToPosition(i);
Log.i("MAIN3ACTIVITY","getting status jkasdfasdf");
value = cdb1.getFlag();
if(value == 1){
Log.i("FLAGCURSOR=====>>>>","Succesful");
releasingNotes = new ReleasingNotes(IntendedChord);
releasingNotes.start();
//break;
}
cdb1.updateFlag(0);
Log.i("FLAGCURSOR=====>>>>",String.valueOf(value));
}
flagCursor = null;
}catch(Exception e){break;}
Log.i("MAIN3ACTIVITY","thread is sleeping");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
}
}catch(Exception e){
}
}
}
In the meantime, the data that were retrieved from the database is using this function:
public Cursor getFlagAll(){
return getReadableDatabase().rawQuery(
"SELECT _ID, flag from flagTable", null);
}
And, the data that were updated to the database through this method:
public int updateFlag(int i) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("flag",i);
return db.update("flagTable" , contentValues , "_ID" + "= ?",new String[]{String.valueOf(1)});
}
Now, above codes will give no error, however, the data that were retrieved from the database is always 1, it keeps trigger a new function. In my above codes, I stated if the value is equal to 1, then the current thread will trigger a new thread to start, When its finished, the program will update the current data to 0. So that, the next round of the infinite loop can stop triggering new thread until a the conditon is met. What is problem overhere? did my codes really updated the new value? or I need to referesh the database every time I updated a new value.
Use Listeners to your database.
use SQLiteTransactionListener and do your things in onCommit()
Some guide in details here :
https://developer.android.com/reference/android/database/sqlite/SQLiteTransactionListener.html and
http://www.programcreek.com/java-api-examples/index.php?api=android.database.sqlite.SQLiteTransactionListener

Retrieving data after modifying data at cloud code

I'm trying to get Parse server date and time but I get to know the only way is to create or update an object then retrieve the value of updatedAt.
My class
//There is only one data/object in this class
Class Test{
int times
};
My cloud code
increment of value "times" is to get current server date and time via getUpdatedAt();
Parse.Cloud.define("updateTimes", function(request, response) {
var test = Parse.Object.extend("Test");
var query = new Parse.Query(test);
query.first({
success: function(results) {
results.increment("times");
results.save();
response.success("success updated");
},
error: function() {
response.error("test lookup failed");
}
});
});
My calling at android studio
//Call updateTimes function at cloud code
ParseCloud.callFunctionInBackground("updateTimes", new HashMap<String, Object>(), new FunctionCallback<String>() {
public void done(String result, ParseException e) {
if (e == null) { //success }
}
});
//Get date and time from server
ParseQuery<ParseObject> query = ParseQuery.getQuery("Test");
query.getInBackground("i6hmOEItvI", new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
if (e == null) {
// success
serverDate = object.getUpdatedAt();
Format formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
date = formatter.format(serverDate);
Log.d("ServerDate",date);
}
});
My problem is the serverDate retrieved from objectId is not correct. The date retrieved is always the older one. However, the updateAt field in database is successfully updated.
I have called ParseCloud.callFunctionInBackground before calling query object.getUpdatedAt();.
Any has any idea why the date I get is not the latest?
It seems a waste to create or touch data just to see what date stamp was written. Why not return a date directly:
Parse.Cloud.define("serverDateTime", function(request, response) {
response.success({dateTime: new Date()});
});

date display in listview in android

I am trying to display a date in descending order in listview in android... I have written a program... It is showing it correctly, but when the first date of the month coming, the last month date are not displaying only one date is showing... What is the reason? How do I improve my code? Please guide me..
my code is here...
public void datesadd()
{
listview.setAdapter(new ListAdapter(this));
cc1=Calendar.getInstance();
int mon1=cc1.getTime().getDate();
Date dd=new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
while(mon1>=count)
{ pos=0;
line=new HashMap<String,String>();
String cdat=String.valueOf(cc1.get(Calendar.DATE));
#SuppressWarnings("deprecation")
String mons=String.valueOf(cc1.get(Calendar.MONTH));
String day1=String.valueOf(cc1.getTime().getDay());
#SuppressWarnings("deprecation")
String year1=String.valueOf(cc1.get(Calendar.YEAR));
try {
dd=format.parse(year1+"-"+mons+"-"+cdat);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
line.put("yeari", year1);
line.put("mont",mons);
line.put("dayi",dd.toString().substring(0, 3));
line.put("datei",cdat);
mon1--;
cc1.add(Calendar.DATE, -1);
Log.v("", "line");
disp.add(line);
// here disp is ArrayList<Hashmap<String,String>> object, i was declared it on top of my main program
}
}
I don't think you're going about date iteration right -- you're just iterating over the value in miliseconds.
Consider this:
/* From your code I'm not sure what count is, but you get the idea, you need
* a Date object here or you can just use a for() loop if you know the number
* |
* V */
while (cc1.getTime().after(count)) {
cc1.add(Calendar.DAY_OF_YEAR /*or month, year, whatever*/, -1);
// and then continue with your own code
line = new HashMap<String,String>();
String cdat = String.valueOf(cc1.get(Calendar.DATE));
// ...
}

Android: Display time using simpledateformat

I am trying to display the time that a user enters, either in a toast or using a basic println command. If the time is in the correct format, I want to enter it in a database along with the current time.
Here is what I have so far:
public void addListenerOnButton ()
{
spinner_hours = (Spinner)findViewById(R.id.hours);
spinner_minutes = (Spinner)findViewById(R.id.minutes);
btnSubmit = (Button) findViewById(R.id.btnSubmit);
btnSubmit.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Date time;
String enteredTime= String.valueOf(spinner_hours.getSelectedItem())+String.valueOf(spinner_minutes.getSelectedItem())+"00";
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
try {
time= format.parse(enteredTime);
System.out.println(enteredTime);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Toast.makeText(MainActivity.this,
// "Your alarm has been set for : " + time,
// Toast.LENGTH_SHORT).show();
}
});
}
If I put the toast (commented below) inside the try block, it doesnt show up when I run the app. If I put a system.out.println it does not print anything. How do I print the entered time?
Also, I want to enter the current time in the same format ("HH:mm:ss") in the database. Any ideas on how to do that?
It's probably throwing an exception, since System.out.println should work. Try replacing this:
String enteredTime= String.valueOf(spinner_hours.getSelectedItem())+String.valueOf(spinner_minutes.getSelectedItem())+"00";
by this:
String enteredTime= String.valueOf(spinner_hours.getSelectedItem())+ ":" + String.valueOf(spinner_minutes.getSelectedItem())+":00";
It seems you're missing the : between hour and minutes and before 00 and the parsing is failing.
First try to print the value got from the Spinner
System.out.println(spinner_hours.getSelectedItem().toString());
System.out.println(spinner_minutes.getSelectedItem().toString());
If this doesn't has any value then the problem is here.

Categories

Resources