In my Android Application, I store the Launcher activity (called MainActivity) in a static variable inside the MainActivity class;
And I am using this static Activity reference to get the application resource, preference and others;
But sometimes, I found that the app is crashed because the object reference is null;
Is there any reason causing the object reference become NULL?
How to prevent this kind of NullPointerException?
My Codes:
MainActivity:
public class MainActivity extends Activity {
private static MainActivity sInstance = null;
public static MainActivity getInstance() {
return sInstance;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sInstance = this;
// other code
}
}
Helper.java:
public static int getColor(int resID) {
return MainActivity.getInstance().getColor(resID);
}
//For this type of issue, please use application class object. If you used Activity class then when //activity destroys then it will become null. So you got the null pointer exception.
public class MyApplication extends Application {
public static MyApplication myApplication = null;
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
myApplication = (MyApplication) getApplicationContext();
}
public static MyApplication getInstance() {
return myApplication;
}
}
//Your method looks like this
public static int getColor(int resID) {
return MyApplication.getInstance().getResources().getColor(resID);
}
Related
I am trying to create a global variable where it can be accessed from any any where including Activity, Fragment and other custom classes.
public class Global extends Application {
private static Global sInstance;
private String mSharedInfoFileName; //can be any custom object
public static Global getInstance() { return sInstance; }
#Override
public void onCreate() {
super.onCreate();
sInstance = this;
initialize();
}
private void initialize() { mSharedInfoFileName = "globalInfo"; }
public String getFileName() { return mSharedInfoFileName; }
private Global() { }
}
and try to use it like this
public class MyFragment extends android.support.v4.app.Fragment {
String s = Global.getInstance().getFileName();
}
even after declaring it in class scope still gave same error
private static Global mGlobal = Global.getInstance();
which give me Attempt to invoice... .Global.getFileName()' on a null object reference. What am I missing?
Thank you
Change this method to static :
public static String getFileName() {
return mSharedInfoFileName;
}
and call it like below:
Global.getFileName();
The mSharedInfoFileName variable has to be static too :
private static String mSharedInfoFileName;
is it possible to get all activities in the application? i have a global integer variable that should be in the ActionBar of every activity. i thought something like this:
for (Layout/Activity l in (all activites)) {
l.setTitle(variable);
}
i already tried it with R.layout but this didnt work for me.
How can i do this or is there a better way to display my variable in all activity labels? later i want to call this code from my set method for the global variable.
There is only one activity running at a time, so you can’t get this kind of references.
Said that, I think the way to go it’s create an int static variable in some class, and called it from your activities.
//SomeClass
public static int xValue = 0;
//ActivityOne || ActivityTwo || ActivityThree ...
String text = String.valueOf(SomeClass.xValue);
SomeClass.xValue = 1;
Because it’s a public static variable, you don’t need to instantiate any object to get/set its value, and it will be accesible from any class. Furthermore, this value will be reachable as long as its class is in the memory, and destroy just when class gets unloaded.
yes it's possible with singleton.
This is how to use singleton:
This is Singleton class:
public class Singleton {
private static Singleton mInstance = null;
private String mTitle;
public void setmTitle(String mtitle){
this.mTitle=mtitle
}
public String getmTitle(){
return mTitle;
}
public static FilterArrayList getInstance(){
if(mInstance == null)
{
mInstance = new FilterArrayList();
}
return mInstance;
}
}
This is the first activity:
public class FirstActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Singleton.mInstance.setmTitle("This is Singleton");
}
}
and in second activity:
public class SecondActivity extends Activity {
String Title;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Title=Singleton.mInstance.getmTitle();
}
}
I keep getting this error about No enclosing instance of my WallpaperService is available. So my program will not compile. What exactly does this error mean...?
Where should I go from here. Below is my constructor for myEngine class. The error happens at my super(); method call.
public final class myEngine extends Engine implements OnSharedPreferenceChangeListener {
LWPService a;
private i b;
private SharedPreferences c;
private LWPService r4_LWPService;
myEngine(LWPService lwpService) {
super();
this.a = r4_LWPService;
this.b = new i(getSurfaceHolder(),
r4_LWPService.getApplicationContext());
this.c = r4_LWPService.getSharedPreferences("settings", 0);
this.c.registerOnSharedPreferenceChangeListener(this);
onSharedPreferenceChanged(this.c, null);
}
... OTHER CODE...
}
Here is the LWPService class
public class LWPService extends WallpaperService {
public void onCreate() {
super.onCreate();
}
public Engine onCreateEngine() {
return new m(this);
}
public void onDestroy() {
super.onDestroy();
}
Your myEngine class should not be static - make it as inner class for LWPService.
I'm trying to track down a new null pointer exception which is appearing in my ACRA logs and which I can't reproduce. Here's the relevant code:
public class MyApplication extends Application {
public void onCreate() {
DataManager.instance().initializeData(this);
}
}
public class DataManager {
private static DataManger instance = new DataManger();
private List<DataModel> dataModels;
private List<I_Callback> callbacks = new ArrayList<I_Callback>();
private boolean isInitialized = false;
private DataManager(){}
public static DataManager instance() {
return instance;
}
public void initializeData(Context context) {
new DataManagerInitializer().execute(context);
}
public void setDataModels(List<DataModel> models) {
dataModels = models;
}
public void synchronized registerInitializeCallbacks(I_Callback callback) {
if (isInitialized) {
callback.executeCallback();
} else {
callbacks.add(callback);
}
}
public void synchronized setInitialized() {
isInitialized = true;
for (I_Callback callback:callbacks) {
callback.executeCallback();
}
callbacks.clear();
}
}
public class DataManagerInitializer extends AsyncTask<Context, Void, Void>{
protected Void doInBackground(Context... contexts){
List<DataModel> dataModels = new ArrayList<DataModel>();
/*various code to create DataModel objects and add to dataModels list*/
DataManager.instance().setDataModels(dataModels);
return null;
}
protected void onPostExecute(Void result) {
DataManager.instance().setInitialized();
}
}
public class ActivityA extends Activity implements I_Callback{
public void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.graphical_layout);
DataManager.instance().registerInitializeCallbacks(this);
}
public void executeCallback() {
/* wire up button to call Activity B */
}
}
public class ActivityB extends Activity {
public void onCreate(Bundle savedInstanceState) {
List<DataModel> dataModels = DataManager.instance().getDataModels();
/* The following line of code throws a null pointer exception
in the stack trace*/
for (int i=0; i < dataModels.size(); i++){
/* do something with the data model */
}
}
}
To break down the above more simply, the application is launched which kicks off the initializion of the data manager singleton. ActivityA, the main activity, launches and waits for the data manager to complete initialization before allowing any actions, wiring up any events, etc. From ActivityA, its not possible to get to ActivityB without the call back method executing and ActivityB is only reachable from ActivityA. The only way for the list of data models to be null in the DataManager is for it to not have been initialized, but I'm struggling to see how this is possible. Any suggestions on how my null pointer may have occurred?
private static DataManger instance = new DataManger();
...
public static DataManager instance() {
return instance;
}
Is where the problem is. So your instance variable is getting garbage collected. As it is instantiated when it is declared, it is not being appropriately re-instantiated. So, try this instead:
private static DataManger instance = null;
...
public static DataManager instance() {
if (instance == null){
instance = new DataManager();
}
return instance;
}
This will ensure the call to instance() (usually called getInstance() but this is only convention), will return a valid single instance of the datamanager. Try to avoid instantiating global variables with their declaration, to avoid this specific problem.
Let's assume that:
you are interacting with the Activity B
press the home button:
start playing with other apps (consuming memory)
at some point the so needs memory and it's gonna start garbage collecting objects, included your "instance".
If that happens when you launch your app the framework will resume the activity B and the npe will happen.
You need to re-create the instance (in the activity B) if it is null.
MAIN ACTIVITY
public class MyActivity() extends Activity
{
onCreate()
{
MyClass myobj=new MyClass();
}
public void Mymethod()
{}
}
//HELPER CLASS IN A SEPARATE FILE
public class MyClass()
{
MyClass(Context context)
{
}
}
I tried to call Mymethod() from an instance of MyClass.
I would really appreciate any help. Thanks.
Why not just pass the activity to the constructor like
public class MyActivity extends Activity {
onCreate(){
MyClass myobj=new MyClass(MyActivity.this);
}
public void myMethod(){
}
}
//HELPER CLASS IN A SEPARATE FILE
public class MyClass{
public MyClass(MyActivity act) {
act.myMethod();
}
}
Make that method as static so you can call without creating the class object
public static void Mymethod()
{}
and call like this way
MainActivity.Mymethod();
This is probably the best way to do it. This is how I'm doing it. It's called a Singleton Design Pattern:
public class MyActivity extends Activity {
private static MainActivity instance;
public static MainActivity getInstance() {
if(instance==null){
setInstance(this);
}
return instance;
}
public static void setInstance(MainActivity instance) {
MainActivity.instance = instance;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setInstance(this);
}
}
If I'm understanding you correctly I believe you can solve your problems using an interface as a callback.
////ACTIVITY/////////////////////////////////
public class MyActivity() extends Activity {
onCreate()
{
MyClass myObj=new MyClass();
//Set the listener on the object. Created as anonymous
myObj.setListener(new MyClass.Listener() {
myMethod();
});
}
}
public void myMethod(){
}
//////Custom Class//////////////////
public class MyClass {
Listener mListener;
public interface Listener {
public void onInterestingEvent();
}
public void setListener(Listener listener) {
mListener = listener;
}
public void someUsefulThingTheClassDoes() {
//Do your code here and when you're ready to call the activity's method do this
mListener.onInterestingEvent();
}
}
I had an inner class that I wanted to pull out into a more general library "Helper" class. I had the same issue you do. I got around it by making the helper class abstract, with a single abstract method. Then in my project package I extended the helper class with a constructor call in the specific class.
public class MyActivity extends Activity {
onCreate() {
MyHelperClass = new MyHelperClass(this, "foobar");
}
public void myMethod() {
// Code...
}
}
// In a different file
public class MyHelperClass extends HelperClass {
private MyActivity mInstance;
public MyHelperClass(MyActivity act, String data) {
super();
this.mInstance = act;
this.mActivity = act; // Useful for calling generic Activity methods in the HelperClass
this.mData = data;
}
protected void callMyActivityMethod() {
mInstance.myMethod();
}
}
// In a different file
public abstract class HelperClass {
protected Activity mActivity;
protected String mData;
public HelperClass() {
// Subclass will set variables
}
protected abstract void callMyActivityMethod();
// More code for all the other stuff the class does
}
In this way, I have a helper class that contains the vast majority of the "work", and all I have to do is make a subclass with the constructor and one method in order to get access to the calling activity's method of interest.
You have to pass instance of MainActivity into another class, then you can call everything public (in MainActivity) from everywhere.
MainActivity.java
public class MainActivity extends AppCompatActivity {
// Instance of AnotherClass for future use
private AnotherClass anotherClass;
#Override
protected void onCreate(Bundle savedInstanceState) {
// Create new instance of AnotherClass and
// pass instance of MainActivity by "this"
anotherClass = new AnotherClass(this);
}
// Method you want to call from another class
public void myMethod(){
...
}
}
AnotherClass.java
public class AnotherClass {
// Main class instance
private MainActivity mainActivity;
// Constructor
public AnotherClass(MainActivity activity) {
// Save instance of main class for future use
mainActivity = activity;
// Call method in MainActivity
mainActivity.myMethod();
}
}
In MainActivity.class file
You have to pass MainActivity context from MainActivity Class. Then in MyClass you have to Get MainActivity context. Remember Context and MyActivity are two different reference.
public class MyActivity extends Activity
{
onCreate(){
MyClass myobj=new MyClass(MyActivity context);
}
public void Mymethod(){}
}
//HELPER CLASS IN A SEPARATE FILE
public class MyClass()
{
MyActivity context;
MyClass(MyActivity context)
{
this.context = context;
this.context.Mymethod();
//Or you can directly use activity context
context.Mymethod();
}
}
I decided to write the HelperClass MyClass as an inner class of MyActivity class. This allows it full access to parent class but the bad thing is now MyClass is restricted to MyActivity class only.
public class MyActivity() extends Activity
{
onCreate()
{
MyClass myobj=new MyClass();
}
public void myMethod()
{
}
}
//INNER CLASS
public class MyClass
{
public MyClass()
{
}
//I can directly access the MyMethod
myMethod();
}