I have some major variables in my main activity that I retrieve their values from internet once the user log in. after that, there are multiple activities that can alter these values in the database but this doesn't reflect in the current loaded values until the user log out/in. (the process where I retrieve data from internet)
what is the best way to update these values in main activity from activity 2 directly without logging out/in?
is there a way to set these variables without making intent and putting the new values in extra bundle? ( I need to change the values without returning back to the activity)
You can perhaps try putting the variables in a custom Application class as static members and then access them from anywhere through Application.xyzStaticMember(). Here's an example:
public class MyTestApp extends Application {
private static List<Int> testList;
public static void setList(List<Int> l) {
testList = l;
}
public static List<Int> getList() {
return testList;
}
}
Then access the members: MyTestApp.setList(null); or MyTestApp.getList();. Oh, and don't forget to use the class in the AndroidManifest.xml file!
<application android:name="com.example.MyTestApp"
/* ...more stuffs */ />
Related
A network call returns a very large json file. However, I just need to use a small portion of this through out the entire app. What is the best strategy on using a small amount of data for several fragments and activities ?
I tried to use shared preferences, but that does not store objects.
For sharing complex data structures or objects, I would extend Application by making a custom sub class. Application object (as the name implies) is accessible to all Activities, even when app transitions from one to another. Below is a very simple example, just to show you the idea. You can modify/adjust that to your needs.
public class MyApplication extends Application {
private X x;
public static void setX(X x) { ... }
public static X getX() { ... }
}
public class ActivityA extends Activity {
...
MyApplication.setX(x);
}
public class ActivityB extends Activity {
...
X x = MyApplication.getX();
}
X can be a collection, data structure, or any object for that matter.
When extending Application, you need to declare it in the manifest. You can find information on how to do that.
Extract the required data from your JSON as a String and then pass it as an extras parameter to the Activities and Fragments that need it:
Intent intent = new Intent(context, SomeActivity.class);
intent.putExtra("YOUR_DATA_KEY", yourJsonString);
startActivity(intent);
and then extract it back again at the Activities and Fragments that need it:
Intent intent = getIntent();
String yourJsonString= intent.getStringExtra("YOUR_DATA_KEY");
I am trying to do something like that , Firstly , there is a MainActivity which stores courses in ArrayList and these courses are showed by listview.After that , I pass to another activity which is called as ShowDetailActivity with startActivity() to show course details when I click list view element.Then, I pass to another activity which is called EditCourseActivity to edit course which is shown by ShowDetailActivity. The problem is that When I want to edit course , I have to access MainActivity 's Arraylist (private) but I cannot pass with startActivity() because MainActivity did restart (reinstalled) that's why there is no courses on arraylist. The question is How can access from EditCourseActivity to MainActivity 's arraylist to show updated courses ?
Store the course information in a singleton class
public class CourseHolder{
public static CourseHolder instance=null;
public static CourseHolder getInstance(){
if(instance==null){
instance=new CourseHolder();
}
return instance;
}
private Course courses[];
private CourseHolder(){
courses=new Course[10];
}
public void setCourse(int index, Course course){
courses[index]=course;
}
public Course[] getCourses(){
return courses;
}
}
In the EditCourseActivity, after editing, store the updated course information in the copy of CourseHolder
In MainActivity.onResume(), call listView.setAdapter(null), then refresh it with the data inside the CourseHolder
As a generic answer: detach the data from its representation. You can achieve this in many ways:
Singleton wrapper for your array list
To be android specific: wrap your array in a ContentProvider
Use Android SDK SQL database support
My MainActivity calls another Activity A which needs to access some members of MainActivity.
What is the best way to send a reference to Main Activity (or its context) to Activity A without resorting to complicated methods like parcelables etc?
There are some heavyweight android wrestling matches here but I am not sure that it is relevant to my problem.
details
I have Alert and Alerted objects in a one-to-many relationship (Alerted represents the various times an Alert was rung).
AlertsListActivity extends ListActivity which displays a list of Alert objects from a SQLite database table (primary key: alertId). It has an AlertsListAdapter.
AlertedsListActivity has a ListFragment which displays a list of Alerted objects from Alerted table (foreign key is alertId from Alert table).
It has an AlertedsListAdapter.
AlertsListActivity needs to call AlertedsListActivity to display the list of Alerted objects. I used startActivityForResult().
Inside AlertedsListAdapter
public View getView(int position, View convertView, ViewGroup parent) {
final Alert alertItem = (Alert) mainActivity.alertsListAdapter.getItem(position);
final Alerted alertedItem = (Alerted) getItem(position);
...
I do need the Alert objects also, in order to display some identifying information from them with each Alerted list item. Hence I need the reference to mainActivity.alertsListAdapter
How can AlertedsListActivity access AlertsListActivity?
Update: Since I did not get any solutions, I implemented a workaround. The data that I needed to access from Main Activity, I modified. So the Alert object was made a parcelable, and the SQLOpenHelper was made a singleton.
This allows the data to be accessed from Activity A.
Here's the simple, common way to do it:
singletons typically have variables like the below example, "useThisContext" or "mainFeedIsHere".
public class Cloud
{
private static Cloud ourInstance = new Cloud();
private Cloud() { Utils.Log("cloud singleton launched"); }
public synchronized static Cloud getInstance()
{
return ourInstance;
}
/////////////////////////////////////////////////
public Context useThisContext;
another example ...
public class Feed
{
private static Feed ourInstance = new Feed();
private Feed()
{
Utils.Log("feed singleton launched");
freshestPostsForDisplay = new ArrayList<ParseObject>();
}
public synchronized static Feed getInstance()
{
return ourInstance;
}
public List<ParseObject> freshestPosts;
public MainActivity mainFeedIsHere;
Quite simply when everything launches (or when it changes), those "things" need to set those variables in the singleton. In other words, those things "tell the singleton, where they are." It's that simple.
So, in the MainActivity perhaps, in onCreate, it might say something like...
CLOUD.useThisContext = this;
FEED.mainFeedIsHere = this;
Then for example inside Feed.java you may have say
mainFeedIsHere.feedReload();
It goes without saying you have to check that they are not null (but how else could it be?) and you have to keep them up-to-date as it were. (i.e., for whatever reason you may want to change "useThisContext" -- again how else could it be?)
{Sometimes you'll have one "centralised" singleton .. perhaps "State" .. to sort of combine all these together - so that anyone can "get to" any of those "exposed" things as needed. This is, really, how game engines go; so that you can say more or less SoundEffects.Booms() or Tanks.Faster() or AI.FindVillains() at any time anywhere.}
Cheers!
Since I did not get any solutions, I implemented a workaround. The data that I needed to access from Main Activity, I modified. So the Alert object was made a parcelable, and the SQLOpenHelper was made a singleton.
This allows the data to be accessed from Activity A.
i have an Android application in which i use a class to store static data among activities, something like:
class Global
{
private static boolean mInitialized = false;
private static String mData = null;
public static void init()
{
mData = "something";
mInitialized = true;
}
public static boolean isInitialized()
{
return mInitialized;
}
public static String getData()
{
return mData;
}
}
So in the main activity onCreate i do:
if( Global.isInitialized() == false )
Global.init();
And then starts other activities, the action flow is:
MainActivity -> ActionActivity -> PluginActivity
Where Main is where i init the Global class, and Action & Plugin is where i use the getData() method of that class.
Now in some cases, i get really strange behaviour ... if something unepected happens in PluginActivity ( NullPointerException for instance ), the activity crashes and the application goes back to the ActionActivity which launched it, but, at this point, during the onCreate of the ActionActivity ( where the Global class is supposed to be initialized ) i get an exception because the getData() returns null ( and isInitialized() is false ) as the Global class was never initialized by the MainActivity.
So, can an object with static members like my Global class be deallocated/cleared/whatever if something like an unexpected exception occurs ?
In general, activities should be independent of each other. You should not depend on them being launched in any particular order, or at all.
Instead, if you need to share global state data between activities, i.e. not just parameter passing in intent extras or results via onActivityResult(), subclass Application, put the init code in its onCreate() and access it from activities using getApplication(). Also remember to declare the application class in your manifest. The system takes care that the application object is there when any of your activities are running.
In Android, whenever application crashes the static variable will be discarded. This is the reason why you are getting NullPointerException. Instead of making the object static create a Parcelable or Serializable class and get and set the fields and then pass that object with the intent. In another activity you can get that Parcelable or Serializable class and you can use its property.
I have a settings menu in my app which controls the units used throughout the app - metric or US units. So when the user selects one of these in the options in the menu, I want my app to use the chosen units throughout in display and calculations.
I plan to do this by storing a boolean in sharedpreferences, then check the value of the boolean every time an activity is opened, and then make the appropriate changes.
Is there a better method to go about doing this?
Thanks
Yes you can extends Applications class and store your data over there using Getter and setter.
So that your data will be retained throughout the Application.
public class SocketManager extends Application {
private static SocketManager singleton;
public int mBluetoothState;
public synchronized static SocketManager getInstance(Context context) {
if (null == singleton) {
singleton = new SocketManager();
}
return singleton;
}
public synchronized void setState(int state) {
mBluetoothState = state;
}
public synchronized int getState() {
return mBluetoothState;
}
}
Access it in Activity like :
SocketManager socketManager = SocketManager.getInstance(this);
socketManager.setState(10);
socketManager.getState();
Add your Application to Maanifest file like this :
<application
android:name=".SocketManager"
android:icon="#drawable/first_aid"
android:label="#string/app_name" >
<activity .... />
</application>
Edit :
You should add your class name that extends Application into Application Tag not on Activity Tag
For further refrence check this link
You can have a look at Android Storage options: http://developer.android.com/guide/topics/data/data-storage.html
However, it seems like for your case SharedPreferences is OK
For just a boolean? If its just a single activity calling SharedPreferencesand assigning it would be fine.
If you have multiple activities in an application you could call it once and load it into a static class and call it that way or subclass the Application class.
But even then it's just a boolean and you should do whatever is most convenient for you.