Connecting two objects from different scenes in Unity [duplicate] - android

How can I pass score value from one scene to another?
I've tried the following:
Scene one:
void Start () {
score = 0;
updateScoreView ();
StartCoroutine (DelayLoadlevel(20));
}
public void updateScoreView(){
score_text.text = "The Score: "+ score;
}
public void AddNewScore(int NewscoreValue){
score = score + NewscoreValue;
updateScoreView ();
}
IEnumerator DelayLoadlevel(float seconds){
yield return new WaitForSeconds(10);
secondsLeft = seconds;
loadingStart = true;
do {
yield return new WaitForSeconds(1);
} while(--secondsLeft >0);
// here I should store my last score before move to level two
PlayerPrefs.SetInt ("player_score", score);
Application.LoadLevel (2);
}
Scene two:
public Text score_text;
private int old_score;
// Use this for initialization
void Start () {
old_score = PlayerPrefs.GetInt ("player_score");
score_text.text = "new score" + old_score.ToString ();
}
but nothing displayed on screen, and there's no error.
Is this the correct way to pass data ?
I am using Unity 5 free edition, develop game for Gear VR (meaning the game will run in android devices).
Any suggestion?

There are many ways to do this but the solution to this depends on the type of data you want to pass between scenes. Components/Scripts and GameObjects are destroyed when new scene is loaded and even when marked as static.
In this answer you can find
Use the static keyword
Use DontDestroyOnLoad
Store the data local
3a PlayerPrefs
3b serialize to XML/JSON/Binary and use FileIO
1. Use the static keyword.
Use this method if the variable to pass to the next scene is not a component, does not inherit from MonoBehaviour and is not a GameObject then make the variable to be static.
Built-in primitive data types such as int, bool, string, float, double. All those variables can be made a static variable.
Example of built-in primitive data types that can be marked as static:
static int counter = 0;
static bool enableAudio = 0;
static float timer = 100;
These should work without problems.
Example of Objects that can be marked as static:
public class MyTestScriptNoMonoBehaviour
{
}
then
static MyTestScriptNoMonoBehaviour testScriptNoMono;
void Start()
{
testScriptNoMono = new MyTestScriptNoMonoBehaviour();
}
Notice that the class does not inherit from MonoBehaviour. This should work.
Example of Objects that cannot be marked as static:
Anything that inherits from Object, Component or GameObject will not work.
1A.Anything that inherits from MonoBehaviour
public class MyTestScript : MonoBehaviour
{
}
then
static MyTestScript testScript;
void Start()
{
testScript = gameObject.AddComponent<MyTestScript>();
}
This will not work because it inherits from MonoBehaviour.
1B.All GameObject:
static GameObject obj;
void Start()
{
obj = new GameObject("My Object");
}
This will not work either because it is a GameObject and GameObject inherit from an Object.
Unity will always destroy its Object even if they are declared with the static keyword.
See #2 for a workaround.
2.Use the DontDestroyOnLoad function.
You only need to use this if the data to keep or pass to the next scene inherits from Object, Component or is a GameObject. This solves the problem described in 1A and 1B.
You can use it to make this GameObject not to destroy when scene unloads:
void Awake()
{
DontDestroyOnLoad(transform.gameObject);
}
You can even use it with the static keyword solve problem from 1A and 1B:
public class MyTestScript : MonoBehaviour
{
}
then
static MyTestScript testScript;
void Awake()
{
DontDestroyOnLoad(transform.gameObject);
}
void Start()
{
testScript = gameObject.AddComponent<MyTestScript>();
}
The testScript variable will now be preserved when new scene loads.
3.Save to local storage then load during next scene.
This method should be used when this is a game data that must be preserved when the game is closed and reopened. Example of this is the player high-score, the game settings such as music volume, objects locations, joystick profile data and so on.
Thare are two ways to save this:
3A.Use the PlayerPrefs API.
Use if you have just few variables to save. Let's say player score:
int playerScore = 80;
And we want to save playerScore:
Save the score in the OnDisable function
void OnDisable()
{
PlayerPrefs.SetInt("score", playerScore);
}
Load it in the OnEnable function
void OnEnable()
{
playerScore = PlayerPrefs.GetInt("score");
}
3B.Serialize the data to json, xml or binaray form then save using one of the C# file API such as File.WriteAllBytes and File.ReadAllBytes to save and load files.
Use this method if there are many variables to save.
General, you need to create a class that does not inherit from MonoBehaviour. This class you should use to hold your game data so that in can be easily serialized or de-serialized.
Example of data to save:
[Serializable]
public class PlayerInfo
{
public List<int> ID = new List<int>();
public List<int> Amounts = new List<int>();
public int life = 0;
public float highScore = 0;
}
Grab the DataSaver class which is a wrapper over File.WriteAllBytes and File.ReadAllBytes that makes saving data easier from this post.
Create new instance:
PlayerInfo saveData = new PlayerInfo();
saveData.life = 99;
saveData.highScore = 40;
Save data from PlayerInfo to a file named "players":
DataSaver.saveData(saveData, "players");
Load data from a file named "players":
PlayerInfo loadedData = DataSaver.loadData<PlayerInfo>("players");

There is another way:
ScriptableObject
ScriptableObjects are basically data containers but may also implement own logic. They "live" only in the Assets like prefabs. They can not be used to store data permanently, but they store the data during one session so they can be used to share data and references between Scenes ... and - something I also often needed - between Scenes and an AnimatorController!
Script
First you need a script similar to MonoBehaviours. A simple example of a ScriptableObject might look like
// fileName is the default name when creating a new Instance
// menuName is where to find it in the context menu of Create
[CreateAssetMenu(fileName = "Data", menuName = "Examples/ExamoleScriptableObject")]
public class ExampleScriptableObject : ScriptableObject
{
public string someStringValue = "";
public CustomDataClass someCustomData = null;
public Transform someTransformReference = null;
// Could also implement some methods to set/read data,
// do stuff with the data like parsing between types, fileIO etc
// Especially ScriptableObjects also implement OnEnable and Awake
// so you could still fill them with permanent data via FileIO at the beginning of your app and store the data via FileIO in OnDestroy !!
}
// If you want the data to be stored permanently in the editor
// and e.g. set it via the Inspector
// your types need to be Serializable!
//
// I intentionally used a non-serializable class here to show that also
// non Serializable types can be passed between scenes
public class CustomDataClass
{
public int example;
public Vector3 custom;
public Dictionary<int, byte[]> data;
}
Create Instances
You can create instances of ScriptableObject either via script
var scriptableObject = ScriptableObject.CreateInstance<ExampleScriptableObject>();
or to make things easier use the [CreateAssetMenu] as shown in the example above.
As this created ScriptabeObject instance lives in the Assets it is not bound to a scene and can therefore be referenced everywhere!
This when you want to share the data between two Scenes or also e.g. the Scene and an AnimatorController all you need to do is reference this ScriptableObject instance in both.
Fill Data
I often use e.g. one component to fill the data like
public class ExampleWriter : MonoBehaviour
{
// Here you drag in the ScriptableObject instance via the Inspector in Unity
[SerializeField] private ExampleScriptableObject example;
public void StoreData(string someString, int someInt, Vector3 someVector, List<byte[]> someDatas)
{
example.someStringValue = someString;
example.someCustomData = new CustomDataClass
{
example = someInt;
custom = someVector;
data = new Dictionary<int, byte[]>();
};
for(var i = 0; i < someDatas.Count; i++)
{
example.someCustomData.data.Add(i, someDatas[i]);
}
example.someTransformReference = transform;
}
}
Consume Data
So after you have written and stored your required data into this ExampleScriptableObject instance every other class in any Scene or AnimatorController or also other ScriptableObjects can read this data on just the same way:
public class ExmpleConsumer : MonoBehaviour
{
// Here you drag in the same ScriptableObject instance via the Inspector in Unity
[SerializeField] private ExampleScriptableObject example;
public void ExampleLog()
{
Debug.Log($"string: {example.someString}", this);
Debug.Log($"int: {example.someCustomData.example}", this);
Debug.Log($"vector: {example.someCustomData.custom}", this);
Debug.Log($"data: There are {example.someCustomData.data.Count} entries in data.", this);
Debug.Log($"The data writer {example.someTransformReference.name} is at position {example.someTransformReference.position}", this);
}
}
Persistence
As said the changes in a ScriptableObject itself are only in the Unity Editor really persistent.
In a build they are only persistent during the same session.
Therefore if needed I often combine the session persistence with some FileIO (as described in this answer's section 3b) for loading and deserializing the values once at session begin (or whenever needed) from the hard drive and serialize and store them to a file once on session end (OnApplicationQuit) or whenever needed.
(This won't work with references of course.)

Besides playerPrefs another dirty way is to preserve an object during level loading by calling DontDestroyOnLoad on it.
DontDestroyOnLoad (transform.gameObject);
Any script attached to the game object will survive and so will the variables in the script.
The DontDestroyOnLoad function is generally used to preserve an entire GameObject, including the components attached to it, and any child objects it has in the hierarchy.
You could create an empty GameObject, and place only the script containing the variables you want preserved on it.

I use a functional approach I call Stateless Scenes.
using UnityEngine;
public class MySceneBehaviour: MonoBehaviour {
private static MySceneParams loadSceneRegister = null;
public MySceneParams sceneParams;
public static void loadMyScene(MySceneParams sceneParams, System.Action<MySceneOutcome> callback) {
MySceneBehaviour.loadSceneRegister = sceneParams;
sceneParams.callback = callback;
UnityEngine.SceneManagement.SceneManager.LoadScene("MyScene");
}
public void Awake() {
if (loadSceneRegister != null) sceneParams = loadSceneRegister;
loadSceneRegister = null; // the register has served its purpose, clear the state
}
public void endScene (MySceneOutcome outcome) {
if (sceneParams.callback != null) sceneParams.callback(outcome);
sceneParams.callback = null; // Protect against double calling;
}
}
[System.Serializable]
public class MySceneParams {
public System.Action<MySceneOutcome> callback;
// + inputs of the scene
}
public class MySceneOutcome {
// + outputs of the scene
}
You can keep global state in the caller's scope, so scene inputs and outputs states can be minimized (makes testing easy). To use it you can use anonymous functions:-
MyBigGameServices services ...
MyBigGameState bigState ...
Splash.loadScene(bigState.player.name, () => {
FirstLevel.loadScene(bigState.player, (firstLevelResult) => {
// do something else
services.savePlayer(firstLevelResult);
})
)}
More info at https://corepox.net/devlog/unity-pattern:-stateless-scenes

There are various way, but assuming that you have to pass just some basic data, you can create a singelton instance of a GameController and use that class to store the data.
and, of course DontDestroyOnLoad is mandatory!
public class GameControl : MonoBehaviour
{
//Static reference
public static GameControl control;
//Data to persist
public float health;
public float experience;
void Awake()
{
//Let the gameobject persist over the scenes
DontDestroyOnLoad(gameObject);
//Check if the control instance is null
if (control == null)
{
//This instance becomes the single instance available
control = this;
}
//Otherwise check if the control instance is not this one
else if (control != this)
{
//In case there is a different instance destroy this one.
Destroy(gameObject);
}
}
Here is the full tutorial with some other example.

you have several options.
The first one I see is to use static variables, which you will not lose their information or value passing from scenes to scenes (since they are not bound to the object). [you lose the information when closing the game, but not when passing between scenes]
the second option is that the player or the object of which you do not want to lose the information, you pass it through the DontDestroyOnLoad function
Here I give you the documentation and the sample code. [You lose the information when you close the game, but not when you go between scenes]
https://docs.unity3d.com/ScriptReference/Object.DontDestroyOnLoad.html
Third is to use the playerPrefab [https://docs.unity3d.com/ScriptReference/PlayerPrefs.html]
that allow you to save information and retrieve it at any time without hanging it even after closing the game [you must be very careful with the latter if you plan to use it to save data even after closing the game since you can lose the data if you close the game suddenly , since player prefab creates a file and retrieves the information from there, but it saves the file at the end or closes the app correctly]

Related

Where should I add the interstitial ad?

I managed to test a simple app and the ads (banner and interstitial) work as expected (the test ones, because the real ones don't, idk why).
The problem is I want to integrate the ads into my main application. I did it for the banner and it works but don't know how to handle the interstitial. For the test app, I called a function when a button was pressed, but here in my app I don't want a button to be pressed in order to show an interstitial, I want this to happen every time the player dies. And I don't know how to do this.
using System;
using UnityEngine;
using GoogleMobileAds.Api;
public class ads : MonoBehaviour
{
private BannerView bannerView;
private InterstitialAd interstitial;
private void RequestBanner()...
private void RequestInterstitial()
{
string adUnitId = "ca-app-pub-3940256099942544/1033173712";
this.interstitial = new InterstitialAd(adUnitId);
AdRequest request = new AdRequest.Builder().Build();
this.interstitial.LoadAd(request);
}
public void GameOverSoShowInterstitial()
{
if (this.interstitial.IsLoaded())
{
this.interstitial.Show();
}
}
void Start()
{
MobileAds.Initialize(initStatus => { });
this.RequestBanner();
this.RequestInterstitial();
}
}
^this is my ads script
but it is located in the second scene named Menu, but since the interstitial should appear when the player dies, I should move that GameObject in the other scene that is the actual game, because it's impossible to die in the 'menu' section. And also, for checking when the ad has to appear I should use the GameManager, right? which is in the game scene, too.
public void GameOver()
{
gameOver = true;
gameScore = score.GetComponent<Score>().getScore();
score.SetActive(false);
Invoke("ActivateGameOverCanvas", 1);
pauseBtn.SetActive(false);
}
^this is the part with the gameover from gamemanager, so I think here I should introduce somehow an instruction that would generate the interstitial ad, but I don't have a clue. I tried to add the 'ads' script to gamemanager too, so at the end of the execution of GameOver function from gamemanager to call the GameOverSoShowInterstitial from ads, but it didn't work.
Any ideas? :(
1. Using objects from another Scene
When it comes to using scripts/objects from once Scene to another we generally put that object into a MonoBehaviour built-in method DontDestroyOnLoad(object);. By Using this method we can make sure that object will not be destroyed when you change the scenes. Assuming that Menu your script is in Menu Scene you can Put that object in DontDestroyOnLoad() method and it will not get destroyed throughout the game.
2. Using the Method from Add script
For this we have multiple options. Like you can find the Object Using GameObject.FindObjectOfType() or GameObject.FindGameObjectWithTag(), etc. But using Gameobject.FindXXX() method can be heavy on performance side. The battre way is to use singleton pattern. In this you basically create an object when your Game Starts(When you need the object). And there will be no other object of the same type (it mean that there will be no other object with the same script attached to the object).
3. See both of the points in Action
Your Ad script
you don't have to change any thing just have to add the Singleton pattern.
using System;
using UnityEngine;
using GoogleMobileAds.Api;
public class ads : MonoBehaviour
{
//This is a static instance of this class so that you can access it from anywhere from you game, Without creating any creating a new Object.(Point #2)
public static ads instance {
get; //These are the getter and setter methods of native C# find the reference below
private set;
}
private Awake()
{
//Check if the instance is already assigned(if there is already an object with this same script attached)
if(instance == null)
{
instance = this; //If instance is empty the assign this object to the instance
DoNotDestroyOnLoad(this.gameObject); //This line will stop Unity from destroying the object when you load new scene.(Point #1)
}
else
{
Destroy(this.gameObject); //since there is already an object of with script destroy this object so that there will be no conflicts between multiple instances of the same class.
}
}
void Start()
{
MobileAds.Initialize(initStatus => { });
this.RequestBanner();
this.RequestInterstitial();
}
public void ShowInterstitialAd()
{
... Show your Ad
}
}
Game Manager Script
public void PlayerDie() //assuming that you have a method for when your Player dies
{
...
ads.instance.ShowInterstitialAd(); //Call the ShowInterstitialAd() method because the object will not be destroyed when you load another scene.
}
I'm basically done here. I hope this helps you. here are some of the reference that might be helpful to understand this further.
Singleton pattern
Getter and setter methods of native C#

How do I `this->addChild(sprite)` from a method that is not my `bool HelloWorld::init()`

I'm trying to get into C++ with Eclipse & Cocos2d-x
I'm having trouble making a method that I can call from anywhere in the class.
My current WORKING code is:
bool HelloWorld::init()
{if ( !LayerColor::initWithColor(ccc4(50, 180, 220, 255) )){
return false;
}
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
origin.y + closeItem->getContentSize().height/2));
//auto menu = Menu::create(closeItem, NULL);
// menu->setPosition(Vec2::ZERO);
//this->addChild(menu, 1);
auto label = LabelTTF::create("Kitty Katch", "Arial", 54);
label->setPosition(Vec2(origin.x + visibleSize.width/2, origin.y + visibleSize.height - label->getContentSize().height));
this->addChild(label, 1);
// add "HelloWorld" splash screen"
//auto sprite = Sprite::create("HelloWorld.png");
//sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
//this->addChild(sprite, 0);
CCSprite *theCloud = CCSprite::create("cloud.png");
theCloud->setPosition(visibleSize.width/2,visibleSize.height/2);
this->addChild(theCloud);
//addACloud ();
return true;
}
And that'll "Add a cloud" to my scene.
but I want to be able to call the void method instead:
void addACloud() {
Size visibleSize = Director::getInstance()->getVisibleSize();
CCSprite *theCloud = CCSprite::create("cloud.png");
theCloud->setPosition(visibleSize.width/2,visibleSize.height/2);
//this->addChild(theCloud); //(Causes error)
HelloWorld->addChild(theCloud); // (error: Cannot use arrow operator on a type)
}
What am I doing wrong guys? thanks
You could create a static member function within your HelloWorld class. You would define something like:
class HelloWorld {
/// ...
public:
static void AddCloud( CCSprite* pCloud ) {
/// Add cloud
}
};
You will then be able to call this from outside the class using the following syntax:
HelloWorld::AddCloud( pCloud );
However, if you are trying to add the cloud to a data structure within the HelloWorld class, a std::vector<CCSprite*> for instance, then you will not be able to do this with a static member function and you will need to create a singleton. This is commonly done by putting extern HelloWorld* g_pHelloWorld; after your class definition, and then when initializing your program, putting: g_pHelloWorld = new HelloWorld; you can then use g_pHelloWorld->AddCloud( pCloud ) instead.
Your addACloud() method need access to your HelloWorld object instance. In your original code
the call to
this->addChild(theCloud);
adds the CCSprite object instance, to the current (this->) HelloWorld object instance. If you want to be able to call
addACloud()
you need to make sure the HelloWorld object instance is available inside the function. This can either be done, by making the AddCloud() function a member function of your HelloWorld class:
class HelloWorld {
// ...
public:
void addACloud();
};
And then modifying your AddCloud implementation to
void HelloWorld::addACloud() {
Size visibleSize = Director::getInstance()->getVisibleSize();
CCSprite *theCloud = CCSprite::create("cloud.png");
theCloud->setPosition(visibleSize.width/2, visibleSize.height/2);
this->addChild(theCloud);
}
Or alternatively if you want to be able to add clouds to different objects (maybe multiple instances of HelloWorld). You can leave AddCloud outside the class definition, but then need to pass the object instance, to which you want to add the clout as an argument:
AddCloud(HelloWorld *instance);
the addChild line in your implementation then becomes:
instance->addChild(theCloud);
It all boils down to having the object instance available inside your function. This happens implicitly in the first approach, by "this" being the object to add to. Or explicitly in the second case where you pass the object instance that you want to add the cloud to.
A theoretical third way is having a global, or static member, or some kind of singleton and making the object instance available through those methods. I would suggest using one of the first two.

how can i persist a model between multiple activities in android?

I'm a beginner to android development, and I'm trying to write my code in an MVC pattern, but I'm having trouble understanding how a model would work. As far as I can tell every time you start a new activity with an intent you are not able to pass a model along with it. As far as i can tell you'd have to reinitialize it each time you start a new activity. Am I missing something? I looked into Parcelable, but it seems that you loose your methods if you make your model Parcelable. right now I'm building a log in system, which checks my local sqllite db on start up if the user has already logged in, and if so it passes to another activity, otherwise it passes to the log in activity, but I wan't to keep that user model alive through all the activities. Is thee a way to do that?
You might want to also consider keeping a static reference around to the model data that you want to share across activities so that you don't have to keep serializing/deserializing the model when switching between activities. You can get away with using Parcelable if your models are small, but at some point, performance may become an issue.
I'm working on a project where we keep the models in a Singleton that we can access throughout the app, and although I generally hate Singleton's for how they can make unit testing more difficult, I have found this approach to perform better with larger models than trying to rely on Android's serialization mechanism.
Here's is a very rough example of what I mean (disclaimer: I have not actually run tested this code, but I hope this illustrates the concept):
You might have a singleton class that I terribly called Models
public class Models {
private static Models instance;
private boolean isInitialized = false;
private User user;
private OtherInterestingModel otherInterestingModel;
private Models() {
}
public static synchronized Models getInstance() {
if (instance == null) {
instance = new Models();
}
return instance;
}
public void loadModels() {
if (!isInitialized) {
/*
* One-time model initialization here.
*/
isInitialized = true;
}
}
public User getUser() {
return user;
}
public OtherInterestingModel getOtherInterestingModel() {
return otherInterestingModel;
}
}
In your LoginActivity, you can initialize the Models class, say, in your onCreate():
public class LoginActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Models.getInstance().loadModels();
User user = Models.getInstance().getUser();
OtherInterestingModelData otherData = Models.getInstance().getOtherInterestingModel();
// Do something with the model data...
}
/*
* This might be called after the user enters data and clicks a login button...
*/
private void login() {
startActivity(new Intent(this, AwesomeLoggedInActivity.class));
}
}
Once the user successfully logs into your app, you could have basically the same code in your main activity:
public class AwesomeLoggedInActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Models.getInstance().loadModels();
User user = Models.getInstance().getUser();
OtherInterestingModelData otherData = Models.getInstance().getOtherInterestingModel();
// Do something with the model data...
}
}
Notice that by having a Singleton, you avoided having to serialize the model data by passing it through the intent that started the main activity.
Yes, you can do that with the Parcelable interface.
You do not lose your class's methods when you implement the Parcelable interface. The interface simply defines a method for writing your member variables to a Parcel object when you need to pass the object around.
Once you retrieve the data from your Intent via getParcelableExtra(), the object is recreated from the Parcel and you can once again treat it as an instance of whatever class it is.
For example, if you have a User class that extends Parcelable, you can bundle it with an Intent by calling putExtra("user", myUser). myUser is then (behind the scenes) packed into a Parcel and attached to the Intent. In your next Activity, you can retrieve that User object with User myUser = (User) getParcelableExtra("user");, and the Parcel will be unpacked and returned to you. You wil once again have a fully functioning User object.

Keeping a session in all application life

I need to create a session and change it at times. In a specific activity should recover it and compare it to a different variable and modify the value of this session. I tried to create a class for this, but the change of activity, the value back to null. I need it to remain until the application is closed.
below:
import android.app.Application;
public class Util extends Application {
private static String idCorrente;
public void onCreate() {
super.onCreate();
idCorrente="0";
}
public static String getIdCorrente() {
return idCorrente;
}
public static void setIdCorrente(String id) {
Util.idCorrente = id;
}
}
I do not know exactly the right way to do it.
You need to store the data on the device somehow. I would recommend reading the Storage Options page of the Android Developers Guide.
Specifically, I think you will find SharedPreferences well-suited for your application.

Solution to access global data from everywhere - efficiently

I need to find a solution that holds and accesses large chunks of complex global data and methods. It has to be accessible from within activities and normal instance variables of various data classes.
This is how I have done it. I would just like to know if there is anything wrong with it or if there is a better/cleaner way.
First I extend Application like recommended many times...
public class MainDataManager extends Application{
public ... large chunks of data in arrays, lists, sets,....
//static variable for singleton access from within instance variables of other classes
public static MainDataManager mainDataManager;
//create and init the global data, and store it in the static variable of the class
#Override
public void onCreate() {
super.onCreate();
//in case it should get called more than once for any reason
if (mainDataManager == null) {
init();
mainDataManager = this;
}
}
Now accessing it from within activities like everywhere recommended...
MainDataManager mainDataManager = (MainDataManager)getApplicationContext();
And since I need to access it from normal instances of data classes ...
public class MyDataClass {
public MainDataManager mainDataManager;
public String name;
public MyDataClass(String namex) {
this.name = namex;
//this is why I defined the static variable within MainDataManager, so
//one has access to it from within the instance of MyDataClass
this.mainDataManager = MainDataManager.mainDataManager;
}
public void examplesForAccessing() {
//some examples on how to access the global data structure and associated methods
mainDataManager.someMethodAccess();
xyz = mainDataManager.someDataAccess;
mainDataManager.someIndirectMethodAccess.clear();
mainDataManager.someOtherData = false;
}
}
Since I have not done this so far, I would like to know if there is anything wrong with this. Memory, efficiency, ...
Thanks very much!
May I add a little sidenote?
I could also have just used a class MainDataClass and access by MainDataClass.var or MainDataClass.method(). Is there any REAL disadvantage?
Is the data in both cases held in heap/stack?
You haven't given much detail about your "large chunks of data" but keep in mind that the onCreate method is the first things that runs when your application is starting and it runs on the main/UI thread. This means that if you do long tasks in your init() method your UX will be poor, not to mention that you are risking an ANR exception.
The solution for that is simple:
Keep your onCreate short
Create a BG thread and use it to run all initialization code
Show a "Splash"/"Welcome" screen with the a proper progressbar while the BG thread is running.

Categories

Resources