I created a library for the recurrent screen in android and when I tried to implement it in my activity I got this error message.
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.app.Activity.getApplicationContext()' on a null object reference
at com.expert.recur.ScreenReco.<init>(ScreenReco.java:15)
at com.expert.recurringscreen.MainActivity.onCreate(MainActivity.java:18)
My code. MainActivity.java:
public class MainActivity extends AppCompatActivity {
ScreenReco screenReco;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
screenReco=new ScreenReco(MainActivity.this);//line 18
screenReco.value = 1000;
screenReco.runnable.run();
}
}
My library:
public class ScreenReco {
Activity activity;
public ScreenReco(Activity activity) {
this.activity = activity;
}
public Context context = activity.getApplicationContext();//line 15
public int value;
public Handler handler = new Handler();
public Runnable runnable = new Runnable() {
@Override
public void run() {
Intent i = new Intent(context, context.getClass());
handler.postDelayed((Runnable) context,value);
context.startActivity(i);
}
};
}
java.lang.NullPointerException: Attempt to invoke virtual method
'android.content.Context android.app.Activity.getApplicationContext()'
on a null object reference
You can create a Constructor
.
A constructor is a special method that is called whenever an object is created using the new keyword.
public class ScreenReco {
Activity activity;
ScreenReco(Activity ctx)
{
this.activity=ctx
}
}
Then
ScreenReco screenReco=new ScreenReco(MainActivity.this);
Or
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
screenReco=new ScreenReco(MainActivity.this);
You are supposed to create an object of ScreenReco class before assigning values to its variables...
public class MainActivity extends AppCompatActivity {
ScreenReco screenReco;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
screenReco=new ScreenReco(); // you are missing this
screenReco.context = this;
screenReco.value = 1000;
screenReco.runnable.run();
}
}
But I strongly recommend you to use constructors for this... it's the good practice
Your MainActivity
is almost fine. But, it is not recommended to call run();
method of Runnable
object ourself. Instead, pass the Runnable
object in a constructor of a Thread
object and call start();
method on the Thread
object and let the system call the run();
method itself when it is appropriate. Your improved MainActivity
may look like this:
public class MainActivity extends AppCompatActivity {
ScreenReco screenReco;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
screenReco=new ScreenReco(MainActivity.this, 1000);//line 18
// screenReco.value = 1000;
// if you want to run `runnable` in a new Thread
// new Thread(screenReco.runnable).start();
//or if you want to run it in the same thread
//new Handler().post(screenReco.runnable);
//screenReco.runnable.run();
}
}
Now moving into your library file ie ScreenReco.java
, it looks like activity
variable hasn't been initialized while you are trying to call getApplicationContext()
method in the class as @PraveenSP's answer has already said. A better practice would be declare all required class variable at once and then initialize them all in the class constructor as:
public class ScreenReco {
// if you need this activity variable to just use as context
// then do not use this variable here just use context only
Activity activity;
// the better practice here is to declare these variable as private
// and pass values for these variables in constructor and initialize them there
public Context context;
public int value;
public Handler handler;
public Runnable runnable;
// constructor improved from your code
public ScreenReco(Activity activity, int value) {
this.activity = activity;// this only if you are using activity
// object to something otherwise get rid of this variable.
this.context = activity.getApplicationContext();
this.handler = new Handler();
this.value = value;
this.runnable = new Runnable() {
@Override
public void run() {
Intent i = new Intent(context, context.getClass());
// handler.postDelayed((Runnable)context, value);
context.startActivity(i);
}
// this is the edit you need
this.handler.postDelayed(runnable, value);
};
}
// this version of constructor is what exactly I would have done by declaring class variable as `private` up there
// public ScreenReco(Context context, int value) {
// this.activity = activity;
// this.context = context;
// this.handler = new Handler();
// also initialize `value` and `runnable` object here
// this.value = value;
// this.runnable = new Runnable() {
// @Override
// public void run() {
// Intent i = new Intent(context, context.getClass());
// handler.postDelayed((Runnable) context,value);
// context.startActivity(i);
// }
// };
// }
}
Also, I'm so confused by the code you wrote inside the runnable
's run()
method. It looks like you are trying to start the MainActivity
from MainActivity
. And, in the line below, you tried to cast context
variable to Runnable
which is very error-prone.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.