Android LWP, How to refresh RenderScript objects after Setting Preferences Changes? - android

I have developed Android LWP using RenderScript. Now I want to add Setting Page and I use Preferences to save the option values.
EG. Initial objects quantity is 10. Then user can change the objects quantity to 20.
I cannot update/refresh/reset/recall the RenderScript to regenerate with the new Setting. How to do it?
I have managed up to onSharedPreferenceChanged, but how to call it in order to regenerate the LWP with the new Setting just after user click?
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
//How to force the renderscript to update here
}
In fact, what I need to know is "How to refresh/clear any drawn object on renderscript?"
Because when setting has been changed, I need to redraw the objects again....
The best things I have managed to go so far is to set the quantity of the objects on the listener like this
private class SPListener implements SharedPreferences.OnSharedPreferenceChangeListener {
#Override
public void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key) {
// TODO Auto-generated method stub
OBJ_COUNT = Integer.parseInt(Utility.getNoOfObjects(mContext));
mScript.set_gObjectsCount(OBJ_COUNT);
mScript.invoke_updateObjects();
}
}
But I got "double" drawn objects. I need to clear existing objects first before I set with new quantity of objects.
EG. Initial objects quantity is 10. Then user can change the objects quantity to 5.
What I got is still 10 objects....with 5 objects are drawn twice/duplicated on top of it. So 5 objects have darker color due this overlay drawn.

I don't use RenderScript, but in my live wallpapers, I keep a class of static variables for all my settings, and an OnPreferenceChangedListener that transfers my settings to that class. In my draw method of the live wallpaper, I just pull the current values of those static variables. Also, when your live wallpaper first starts, you need to tell the settings class to update all of its variables to current values.

Finally managed to fix it...Nothing wrong on the technique. The location to update is also correct on onSharedPreferenceChanged. But I manage to redraw everything perfectly now.

Related

Save User-Created views (e.g. buttons and text views) to be restored when using the app again

My Activity has 6 default CardViews, each cardview contains a Constraint layout and the constraint layout contains a couple of Text views
my problem is, I wanted to add an "ADD" which would take you through some steps and eventually create a new cardview, but how would I save that view created by the user so when they close the app and enter again it would still be there? (Users could add multiple cardviews)
I'm familiar with SharedPreferences but i don't think it would be possible in this case because it requires me to save the data in a declared string and the user simply doesn't have access to that
What i want to do is something similar to Alarm apps, when you can add multiple alarms, delete alarms etc and it would be there even if you restart the Alarm app
What you need is not saving the view itself, but rather save info or state of each object after user modifies it. And you are right about SharedPreferences, it wouldn't be the best option for this...
So, I would recommend two things:
Saving & getting your Cardviews data should be from a custom class (for ex: Alarm) that has properties.
package my.app.example;
class Alarm{
long time;
boolean isOn;
String label;
public Alarm(long time, boolean isOn, String label){
this .time = time;
this .isOn = isOn;
this .label = label;
}
}
And you can use it as follows:
long timeFromDatabase = ...;//get time value from database
boolean isOnFromDatabase= ...;//get isOn value from database
String labelFromDatabase= ...;//get label value from database
Alarm alarm1 = new Alarm(timeFromDatabase, isOnFromDatabase, labelFromDatabase);
After, you can add each Alarm object to a List, and then pass it to your Adapter
A database (I recommend Sqlite or Json) to which you will save each Alarm data (time, isOn, ...)
Remark Alarm is just an example! Feel free to use whatever name and properties that suit your project
See this tutorial it's way is similar to what I suggested: https://www.javatpoint.com/android-sqlite-tutorial, he saves contacts to an sqlite offline database and get them later.

Android Life Cycle confusion

Updated to describe the requested code; the updates are at the end.
I'm trying to do something that seems like it should be simple but the Android Life Cycle doesn't seem to be working as described. I expect this is a misunderstanding on my part, not a bug in Android!
I am new to Android and am just getting familiar with the Android Life Cycle after developing Java apps for Windows so I'm still struggling with a lot of new ideas, especially the Life Cycle.
I have nearly finished my first app, which is based on a RecyclerView. It shows a bunch of sales records (each representing one sale) of a small company. Users can click on a FloatingActionButton to report a new sale or click on edit or remove icons on the individual records to change the details of a sale or delete it entirely. Each of these things has its own activity. Also, there is a SettingsActivity to show settings.
One of the settings lets the user select from amongst three different date formats for displaying the date of the sale. When I back out of Settings (by hitting the back button), I want to see the visible rows using the newly-changed date format immediately but this is NOT happening. Up until now, I would just click on the buttons to take me to one of the other activities, then click the cancel button when I get there; on returning to my main activity, I would see the new date format.
I don't feel my user should have to go to that other activity; simply returning from Settings should change the dates immediately. I started looking at the Android Life Cycle. As I read the documentation, I should be overriding the onResume() method and issuing a notifyDataChanged() to the Adapter that controls the RecyclerView to get it to rebind the visible rows, using the new date format.
Unfortunately, that has no effect whatever that I can see. Here's my onResume:
#Override
protected void onResume() {
super.onResume();
mAdapter.notifyDataSetChanged();
}
Am I doing the notifyDataSetChanged() in the wrong method? If not, why doesn't it work? If it is the wrong method, which method should I be overriding?
Is there any particularly good text or video tutorial explaining the Life Cycle that I should be reading or viewing?
Updates
The date format is set in my SettingsActivity, which is the default one provided in the SettingsActivity template, tailored to meet my needs. All I've touched is the General settings. I replaced all of the ones from the template with six of my own settings. One is called Date format and defaults to YYYY-MM-DD; there are two other choices.
My main activity, which is the one that invokes SettingsActivity via a menu option, gets the value of the date format from the default SharedPreferences. This is because I don't want to look up the value of the Date format once for every row in the ArrayList but just once for all the rows in the ArrayList. I pass the value of the Date format to the Adapter via its constructor. The format gets used in OnBindViewHolder() to control the appearance of the date on the various sales records.
Define a set method to your adapter,
public class MyAdapter extends RecyclerView.Adapter<AdapterContactList.ViewHolder> {
private String dateFormat;
.....
public void setDateFormat(String dateFormat) {
this.dateFormat = dateFormat;
}
}
After user change the dateformat; set it to your adapter, then notify datas for change. That means, you need set new dateformat before notifyDataSetChanged method; because adapter doesn't know the new value.
#Override
protected void onResume() {
super.onResume();
String newDateFormat = getFromSharedPreferencesOrInstantly();
mAdapter.setDateFormat(newDateFormat);
mAdapter.notifyDataSetChanged();
}

Android view change onComplete

I have a card game that uses a programatically set GridView with a custom ArrayAdapter hooked to an array of 'cards' to animate flipping the cards upon dealing via getView(). I need to know when all the cards are done flipping so that the game can deal again or possibly perform another action if it needs to based on the current state of the cards. This has to happen after the last animation of the current flip of course (I already know the state of the cards but I want to deal or other action to happen "in order" after the cards are flipped and before the user can make any changes to the screen). I know that I can count and set a global variable and/or poll for the state but I would prefer to be able to do it the 'correct' way - if there is such a way better than a global count/poll. I can't figure out how better to do it. Suggestions appreciated!
If you want to trace detailed states of the cards through out your game, I would suggest you to set one object for each of the cards.ie
public class Card {
public enum CardState {
CARD_FACE, CARD_FLIPPING, CARD_BACK
}
private CardState cardState;
//other card object variables
public Card(){
cardState = CardState.CARD_BACK;
//other card object variables default status
}
public CardState getCardState() {
return cardState;
}
public void setCardState(CardState cardState) {
this.cardState = cardState;
}
//other getters and setters
}
Use an array to store all the card objects in your game controller. By checking the array, you can determine the next action.

Restoring an ArrayList of custom objects

In my app (which is a game), I have an 'Enemy' class, for example like so:
public class Enemy extends Sprite implements Serializable {
public Enemy(EnemyType type){
super();
}
}
I have then declared an ArrayList like so:
ArrayList<Enemy> enemyList = new ArrayList<Enemy>();
To which I can add enemies:
enemyList.add(bird);
enemyList.add(bee);
When saving to the Bundle I simply put:
bundle.putSerializable("Enemies", enemyList);
And when restoring from the Bundle, I have this:
enemyList = (ArrayList<Enemy>) savedState.getSerializable("Enemies");
Now, it does seem to restore the arraylist (I can check it's size and it is always correct - ie, the same size on restoring from the bundle, as it was when saving to the bundle.
I have also logged for example, the first index of the ArrayList and sure enough it lists the enemy instance as being there.
However, if I try to manipulate the ArrayList at any time post-restoration, I get an exception telling me that I'm trying to perform [whatever action] on a Null object (enemyList).
If I simply populate the list myself, so have something like:
enemyList = (ArrayList<Enemy>) savedState.getSerializable("Enemies");
enemyList.add(bird);
enemyList.add(bee);
Then everything works as expected.
I'm assuming this has something to do with the fact that the super class of Enemy isn't serialised? However, if I serialise this, I get a 'notSerializableException' error.
Please note, I'm not really too worried about saving/restoring the actual Enemy objects to the Bundle, I can handle this manually. Rather I just want the list to be in the same state as it was. And I thought that what was stored in the ArrayList were just references to the objects in question, therefore I can't work out why this is happening?
Any ideas what I'm doing wrong or is there a better method to achieve that which I'm trying to achieve?
The recommended way of doing this in Android is to make the objects you want to persist to be Parcelable. This is a type of serialization specific to Android.
Have a look at the official documentation here

Preference Screen as interface for database?

Is it possible to use a preference screen as a simple interface to read and write values to a database?
Basically, I like the way the preference screen looks and operates, but preferences aren't a suitable way to store all the data I have.
I know how to get it to display correctly, but I'm unsure on how to access the values represented on the screen, and how to keep it from writing a preference file.
Is this even a good idea?
Thanks.
Just to follow this up for anyone that is interested. I got it working by using a Preference.OnPreferenceChangeListener() to store the value as a int or string or whatever. For example:
et_model.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener(){
public boolean onPreferenceChange(Preference preference, Object newValue) {
String val = (String) newValue;
preference.setSummary(val);
model = val;
return true;
}
});
Then once the user presses done, I add the data to the database in the usual way with my SQLight database helper class.
When I load the values from the database, I simply use Preference.SetText(String), and Preference.SetSummary(String).
I guess it is still writing a preference file because if I don't set the preference's text it will load with whatever was set last, but I don't think this is a problem. I could also delete the preference file when I close the activity or something...
If you want a good example, just look at the source for the AlarmClock (now DeskClock) Look at SetAlarm.java and set_alarm.xml for the layout(Save and cancel keys) and alarm_prefs.xml for the actual preference layout.
I don't think that is such a hot idea, especially if you plan on having a tone of data in your database. How ever if you did want to do it, I would just extend the Preference widgets that you will use and have them interface with the database. For example, lets say you have 10 items in a table and you want to select one item (row in the database), you would override the ListPreference and fill it with the content of the applicable database row.

Categories

Resources